1######################################################################## 2# # 3# This software is part of the ast package # 4# Copyright (c) 1982-2009 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 28Command=${0##*/} 29integer Errors=0 30 31unset HISTFILE 32export LC_ALL=C ENV= 33 34ulimit -c 0 35 36tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; } 37trap "cd /; rm -rf $tmp" EXIT 38 39if [[ $( ${SHELL-ksh} -s hello<<-\! 40 print $1 41 ! 42 ) != hello ]] 43then err_exit "${SHELL-ksh} -s not working" 44fi 45x=$( 46 set -e 47 false && print bad 48 print good 49) 50if [[ $x != good ]] 51then err_exit 'sh -e not working' 52fi 53[[ $($SHELL -D -c 'print hi; print $"hello"') == '"hello"' ]] || err_exit 'ksh -D not working' 54 55env=$tmp/.env 56print $'(print -u1 aha) &>/dev/null\n(print -u2 aha) &>/dev/null' > $env 57rc=$tmp/.kshrc 58print $'PS1=""\nfunction env_hit\n{\n\tprint OK\n}' > $rc 59 60export ENV=/.$env 61if [[ ! -o privileged ]] 62then 63 got=$($SHELL -E -c : 2>/dev/null) 64 if [[ $g ]] 65 then 66 got=$(printf %q "$got") 67 err_exit "\$ENV file &>/dev/null does not redirect stdout -- expected '', got $got" 68 fi 69 got=$($SHELL -E -c : 2>&1 >/dev/null) 70 if [[ $got != *nonstandard* || $got == *$'\n'* ]] 71 then 72 got=$(printf %q "$got") 73 err_exit "\$ENV file &>/dev/null does not redirect stderr -- expected one diagnostic line, got $got" 74 fi 75fi 76 77export ENV=/.$rc 78if [[ -o privileged ]] 79then 80 [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] && 81 err_exit 'privileged nointeractive shell reads $ENV file' 82 [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] && 83 err_exit 'privileged -E reads $ENV file' 84 [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] && 85 err_exit 'privileged +E reads $ENV file' 86 [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] && 87 err_exit 'privileged --rc reads $ENV file' 88 [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] && 89 err_exit 'privileged --norc reads $ENV file' 90else 91 [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] && 92 err_exit 'nointeractive shell reads $ENV file' 93 [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] || 94 err_exit '-E ignores $ENV file' 95 [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] && 96 err_exit '+E reads $ENV file' 97 [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] || 98 err_exit '--rc ignores $ENV file' 99 [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] && 100 err_exit '--norc reads $ENV file' 101 [[ $(print env_hit | $SHELL -i 2>&1) == "OK" ]] || 102 err_exit '-i ignores $ENV file' 103fi 104 105export ENV= 106if [[ -o privileged ]] 107then 108 [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] && 109 err_exit 'privileged nointeractive shell reads $HOME/.kshrc file' 110 [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] && 111 err_exit 'privileged -E ignores empty $ENV' 112 [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] && 113 err_exit 'privileged +E reads $HOME/.kshrc file' 114 [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] && 115 err_exit 'privileged --rc ignores empty $ENV' 116 [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] && 117 err_exit 'privileged --norc reads $HOME/.kshrc file' 118else 119 [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] && 120 err_exit 'nointeractive shell reads $HOME/.kshrc file' 121 [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] && 122 err_exit '-E ignores empty $ENV' 123 [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] && 124 err_exit '+E reads $HOME/.kshrc file' 125 [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] && 126 err_exit '--rc ignores empty $ENV' 127 [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] && 128 err_exit '--norc reads $HOME/.kshrc file' 129fi 130 131unset ENV 132if [[ -o privileged ]] 133then 134 [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] && 135 err_exit 'privileged nointeractive shell reads $HOME/.kshrc file' 136 [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] && 137 err_exit 'privileged -E reads $HOME/.kshrc file' 138 [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] && 139 err_exit 'privileged +E reads $HOME/.kshrc file' 140 [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] && 141 err_exit 'privileged --rc reads $HOME/.kshrc file' 142 [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] && 143 err_exit 'privileged --norc reads $HOME/.kshrc file' 144else 145 [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] && 146 err_exit 'nointeractive shell reads $HOME/.kshrc file' 147 [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] || 148 err_exit '-E ignores $HOME/.kshrc file' 149 [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] && 150 err_exit '+E reads $HOME/.kshrc file' 151 [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] || 152 err_exit '--rc ignores $HOME/.kshrc file' 153 [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] && 154 err_exit '--norc reads $HOME/.kshrc file' 155fi 156 157rm -rf $tmp/.kshrc 158 159if command set -G 2> /dev/null 160then cd $tmp 161 mkdir bar foo 162 > bar.c > bam.c 163 > bar/foo.c > bar/bam.c 164 > foo/bam.c 165 set -- **.c 166 expected='bam.c bar.c' 167 [[ $* == $expected ]] || 168 err_exit "-G **.c failed -- expected '$expected', got '$*'" 169 set -- ** 170 expected='bam.c bar bar.c bar/bam.c bar/foo.c foo foo/bam.c' 171 [[ $* == $expected ]] || 172 err_exit "-G ** failed -- expected '$expected', got '$*'" 173 set -- **/*.c 174 expected='bam.c bar.c bar/bam.c bar/foo.c foo/bam.c' 175 [[ $* == $expected ]] || 176 err_exit "-G **/*.c failed -- expected '$expected', got '$*'" 177 set -- **/bam.c 178 expected='bam.c bar/bam.c foo/bam.c' 179 [[ $* == $expected ]] || 180 err_exit "-G **/bam.c failed -- expected '$expected', got '$*'" 181 cd ~- 182fi 183 184cd $tmp 185t="<$$>.profile.<$$>" 186echo "echo '$t'" > .profile 187cp $SHELL ./-ksh 188if [[ -o privileged ]] 189then 190 [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] && 191 err_exit 'privileged -l reads .profile' 192 [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] && 193 err_exit 'privileged --login reads .profile' 194 [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>&1) == *$t* ]] && 195 err_exit 'privileged --login-shell reads .profile' 196 [[ $(HOME=$PWD $SHELL --login_shell </dev/null 2>&1) == *$t* ]] && 197 err_exit 'privileged --login_shell reads .profile' 198 [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>&1) == *$t* ]] && 199 err_exit 'privileged exec -a -ksh ksh reads .profile' 200 [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] && 201 err_exit 'privileged ./-ksh reads .profile' 202 [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] && 203 err_exit 'privileged ./-ksh -p reads .profile' 204else 205 [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] || 206 err_exit '-l ignores .profile' 207 [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] || 208 err_exit '--login ignores .profile' 209 [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>&1) == *$t* ]] || 210 err_exit '--login-shell ignores .profile' 211 [[ $(HOME=$PWD $SHELL --login_shell </dev/null 2>&1) == *$t* ]] || 212 err_exit '--login_shell ignores .profile' 213 [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>/dev/null) == *$t* ]] || 214 err_exit 'exec -a -ksh ksh 2>/dev/null ignores .profile' 215 [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>&1) == *$t* ]] || 216 err_exit 'exec -a -ksh ksh 2>&1 ignores .profile' 217 [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] || 218 err_exit './-ksh ignores .profile' 219 [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] && 220 err_exit './-ksh -p does not ignore .profile' 221fi 222cd ~- 223rm -rf $tmp/.profile 224 225# { exec interactive login_shell restricted xtrace } in the following test 226 227for opt in \ 228 allexport all-export all_export \ 229 bgnice bg-nice bg_nice \ 230 clobber emacs \ 231 errexit err-exit err_exit \ 232 glob \ 233 globstar glob-star glob_star \ 234 gmacs \ 235 ignoreeof ignore-eof ignore_eof \ 236 keyword log markdirs monitor notify \ 237 pipefail pipe-fail pipe_fail \ 238 trackall track-all track_all \ 239 unset verbose vi \ 240 viraw vi-raw vi_raw 241do old=$opt 242 if [[ ! -o $opt ]] 243 then old=no$opt 244 fi 245 246 set --$opt || err_exit "set --$opt failed" 247 [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" 248 [[ -o no$opt ]] && err_exit "[[ -o no$opt ]] failed" 249 [[ -o no-$opt ]] && err_exit "[[ -o no-$opt ]] failed" 250 [[ -o no_$opt ]] && err_exit "[[ -o no_$opt ]] failed" 251 [[ -o ?$opt ]] || err_exit "[[ -o ?$opt ]] failed" 252 [[ -o ?no$opt ]] || err_exit "[[ -o ?no$opt ]] failed" 253 [[ -o ?no-$opt ]] || err_exit "[[ -o ?no-$opt ]] failed" 254 [[ -o ?no_$opt ]] || err_exit "[[ -o ?no_$opt ]] failed" 255 256 set --no$opt || err_exit "set --no$opt failed" 257 [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" 258 [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed" 259 260 set --no-$opt || err_exit "set --no-$opt failed" 261 [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" 262 [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed" 263 264 set --no_$opt || err_exit "set --no_$opt failed" 265 [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" 266 [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed" 267 268 set -o $opt || err_exit "set -o $opt failed" 269 [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" 270 set -o $opt=1 || err_exit "set -o $opt=1 failed" 271 [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" 272 set -o no$opt=0 || err_exit "set -o no$opt=0 failed" 273 [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" 274 set --$opt=1 || err_exit "set --$opt=1 failed" 275 [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" 276 set --no$opt=0 || err_exit "set --no$opt=0 failed" 277 [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" 278 279 set -o no$opt || err_exit "set -o no$opt failed" 280 [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" 281 set -o $opt=0 || err_exit "set -o $opt=0 failed" 282 [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" 283 set -o no$opt=1 || err_exit "set -o no$opt=1 failed" 284 [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" 285 set --$opt=0 || err_exit "set --$opt=0 failed" 286 [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" 287 set --no$opt=1 || err_exit "set --no$opt=1 failed" 288 [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" 289 290 set -o no-$opt || err_exit "set -o no-$opt failed" 291 [[ -o no-$opt ]] || err_exit "[[ -o no-$opt ]] failed" 292 293 set -o no_$opt || err_exit "set -o no_$opt failed" 294 [[ -o no_$opt ]] || err_exit "[[ -o no_$opt ]] failed" 295 296 set +o $opt || err_exit "set +o $opt failed" 297 [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" 298 299 set +o no$opt || err_exit "set +o no$opt failed" 300 [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" 301 302 set +o no-$opt || err_exit "set +o no-$opt failed" 303 [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" 304 305 set +o no_$opt || err_exit "set +o no_$opt failed" 306 [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" 307 308 set --$old 309done 310 311for opt in \ 312 exec interactive login_shell login-shell logi privileged \ 313 rc restricted xtrace 314do [[ -o $opt ]] 315 y=$? 316 [[ -o no$opt ]] 317 n=$? 318 case $y$n in 319 10|01) ;; 320 *) err_exit "[[ -o $opt ]] == [[ -o no$opt ]]" ;; 321 esac 322done 323 324for opt in \ 325 foo foo-bar foo_bar 326do if [[ -o ?$opt ]] 327 then err_exit "[[ -o ?$opt ]] should fail" 328 fi 329 if [[ -o ?no$opt ]] 330 then err_exit "[[ -o ?no$opt ]] should fail" 331 fi 332done 333 334[[ $(set +o) == $(set --state) ]] || err_exit "set --state different from set +o" 335set -- $(set --state) 336[[ $1 == set && $2 == --default ]] || err_exit "set --state failed -- expected 'set --default *', got '$1 $2 *'" 337shift 338restore=$* 339shift 340off= 341for opt 342do case $opt in 343 --not*) opt=${opt/--/--no} ;; 344 --no*) opt=${opt/--no/--} ;; 345 --*) opt=${opt/--/--no} ;; 346 esac 347 off="$off $opt" 348done 349set $off 350state=$(set --state) 351default=$(set --default --state) 352[[ $state == $default ]] || err_exit "set --state for default options failed: expected '$default', got '$state'" 353set $restore 354state=$(set --state) 355[[ $state == "set $restore" ]] || err_exit "set --state after restore failed: expected 'set $restore', got '$state'" 356 357typeset -a pipeline 358pipeline=( 359 ( nopipefail=0 pipefail=1 command='false|true|true' ) 360 ( nopipefail=0 pipefail=1 command='true|false|true' ) 361 ( nopipefail=1 pipefail=1 command='true|true|false' ) 362 ( nopipefail=1 pipefail=1 command='false|false|false' ) 363 ( nopipefail=0 pipefail=0 command='true|true|true' ) 364 ( nopipefail=0 pipefail=0 command='print hi|(sleep 1;/bin/cat)>/dev/null' ) 365) 366set --nopipefail 367for ((i = 0; i < ${#pipeline[@]}; i++ )) 368do eval ${pipeline[i].command} 369 status=$? 370 expected=${pipeline[i].nopipefail} 371 [[ $status == $expected ]] || 372 err_exit "--nopipefail '${pipeline[i].command}' exit status $status -- expected $expected" 373done 374ftt=0 375set --pipefail 376for ((i = 0; i < ${#pipeline[@]}; i++ )) 377do eval ${pipeline[i].command} 378 status=$? 379 expected=${pipeline[i].pipefail} 380 if [[ $status != $expected ]] 381 then err_exit "--pipefail '${pipeline[i].command}' exit status $status -- expected $expected" 382 (( i == 0 )) && ftt=1 383 fi 384done 385if (( ! ftt )) 386then exp=10 387 got=$(for((n=1;n<exp;n++))do $SHELL --pipefail -c '(sleep 0.1;false)|true|true' && break; done; print $n) 388 [[ $got == $exp ]] || err_exit "--pipefail -c '(sleep 0.1;false)|true|true' fails with exit status 0 (after $got/$exp iterations)" 389fi 390 391echo=$(whence -p echo) 392for ((i=0; i < 20; i++)) 393do if ! x=$(true | $echo 123) 394 then err_exit 'command substitution with wrong exit status with pipefai' 395 break 396 fi 397done 398( 399 set -o pipefail 400 false | true 401 (( $? )) || err_exit 'pipe not failing in subshell with pipefail' 402) | wc >/dev/null 403$SHELL -c 'set -o pipefail; false | $(whence -p true);' && err_exit 'pipefail not returning failure with sh -c' 404exp='1212 or 1221' 405got=$( 406 set --pipefail 407 pipe() { date | cat > /dev/null ;} 408 print $'1\n2' | 409 while read i 410 do if pipe $tmp 411 then { print -n $i; sleep 2; print -n $i; } & 412 fi 413 done 414 wait 415) 416[[ $got == @((12|21)(12|21)) ]] || err_exit "& job delayed by --pipefail, expected '$exp', got '$got'" 417$SHELL -c '[[ $- == *c* ]]' || err_exit 'option c not in $-' 418> $tmp/.profile 419for i in i l r s D E a b e f h k n t u v x B C G H 420do HOME=$tmp ENV= $SHELL -$i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not in \$-" 421 [[ \$- == *$i* ]] || exit 1 422 ++EOF++ 423done 424letters=ilrabefhknuvxBCGE 425integer j=0 426for i in interactive login restricted allexport notify errexit \ 427 noglob trackall keyword noexec nounset verbose xtrace braceexpand \ 428 noclobber globstar rc 429do HOME=$tmp ENV= $SHELL -o $i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not equivalent to ${letters:j:1}" 430 [[ \$- == *${letters:j:1}* ]] || exit 1 431 ++EOF++ 432 ((j++)) 433done 434 435export ENV= 436histfile=$tmp/history 437exp=$(HISTFILE=$histfile $SHELL -c $'function foo\n{\ncat\n}\ntype foo') 438for var in HISTSIZE HISTFILE 439do got=$( ( HISTFILE=$histfile $SHELL -ic $'unset '$var$'\nfunction foo\n{\ncat\n}\ntype foo\nexit' ) 2>&1 ) 440 got=${got##*': '} 441 [[ $got == "$exp" ]] || err_exit "function definition inside (...) with $var unset fails -- got '$got', expected '$exp'" 442 got=$( { HISTFILE=$histfile $SHELL -ic $'unset '$var$'\nfunction foo\n{\ncat\n}\ntype foo\nexit' ;} 2>&1 ) 443 got=${got##*': '} 444 [[ $got == "$exp" ]] || err_exit "function definition inside {...;} with $var unset fails -- got '$got', expected '$exp'" 445done 446( unset HISTFILE; $SHELL -ic "HISTFILE=$histfile" 2>/dev/null ) || err_exit "setting HISTFILE when not in environment fails" 447 448# the next tests loop on all combinations of 449# { SUB PAR CMD ADD } 450 451SUB=( 452 ( BEG='$( ' END=' )' ) 453 ( BEG='${ ' END='; }' ) 454) 455PAR=( 456 ( BEG='( ' END=' )' ) 457 ( BEG='{ ' END='; }' ) 458) 459CMD=( command-kill script-kill ) 460ADD=( '' '; :' ) 461 462cd $tmp 463print $'#!'$SHELL$'\nkill -KILL $$' > command-kill 464print $'kill -KILL $$' > script-kill 465chmod +x command-kill script-kill 466export PATH=.:$PATH 467exp='Killed' 468for ((S=0; S<${#SUB[@]}; S++)) 469do for ((P=0; P<${#PAR[@]}; P++)) 470 do for ((C=0; C<${#CMD[@]}; C++)) 471 do for ((A=0; A<${#ADD[@]}; A++)) 472 do cmd="${SUB[S].BEG}${PAR[P].BEG}${CMD[C]}${PAR[P].END} 2>&1${ADD[A]}${SUB[S].END}" 473 eval got="$cmd" 474 got=${got##*': '} 475 got=${got%%'('*} 476 [[ $got == "$exp" ]] || err_exit "$cmd failed -- got '$got', expected '$exp'" 477 done 478 done 479 done 480done 481 482$SHELL 2> /dev/null -c '{; true ;}' || err_exit 'leading ; causes syntax error in brace group' 483$SHELL 2> /dev/null -c '(; true ;)' || err_exit 'leading ; causes syntax error in parenthesis group' 484 485print 'for ((i = 0; i < ${1:-10000}; i++ )); do printf "%.*c\n" 15 x; done' > pipefail 486chmod +x pipefail 487$SHELL --pipefail -c './pipefail 10000 | sed 1q' >/dev/null 2>&1 & 488tst=$! 489{ sleep 4; kill $tst; } 2>/dev/null & 490spy=$! 491wait $tst 2>/dev/null 492status=$? 493if [[ $status == 0 || $(kill -l $status) == PIPE ]] 494then kill $spy 2>/dev/null 495else err_exit "pipefail pipeline bypasses SIGPIPE and hangs" 496fi 497wait 498 499exit $((Errors)) 500