diff options
author | chin <none@none> | 2007-08-17 12:01:52 -0700 |
---|---|---|
committer | chin <none@none> | 2007-08-17 12:01:52 -0700 |
commit | da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968 (patch) | |
tree | 5280d3b78e289fe9551371ab6e7f15ef9944ea14 /usr/src/lib/libshell/common/tests | |
parent | 073dbf9103ef2a2b05d8a16e2d26db04e0374b0e (diff) | |
download | illumos-gate-da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968.tar.gz |
6437624 RFE: Add ksh93 (as /usr/bin/ksh93) and libshell.so to OS/Net
6505835 AST tools and library (libpp) required for creating l10n messages for ksh93
PSARC/2006/550 Korn Shell 93 Integration
PSARC/2006/587 /etc/ksh.kshrc for ksh93
PSARC/2007/035 ksh93 Amendments
Contributed by Roland Mainz <roland.mainz@nrubsig.org>
--HG--
rename : usr/src/lib/libcmd/common/mapfile-vers => deleted_files/usr/src/lib/libcmd/common/mapfile-vers
rename : usr/src/lib/libcmd/common/placeholder.c => deleted_files/usr/src/lib/libcmd/common/placeholder.c
Diffstat (limited to 'usr/src/lib/libshell/common/tests')
30 files changed, 7436 insertions, 0 deletions
diff --git a/usr/src/lib/libshell/common/tests/alias.sh b/usr/src/lib/libshell/common/tests/alias.sh new file mode 100644 index 0000000000..bf7f17f5f6 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/alias.sh @@ -0,0 +1,83 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +alias foo='print hello' +if [[ $(foo) != hello ]] +then err_exit 'foo, where foo is alias for "print hello" failed' +fi +if [[ $(foo world) != 'hello world' ]] +then err_exit 'foo world, where foo is alias for "print hello" failed' +fi +alias foo='print hello ' +alias bar=world +if [[ $(foo bar) != 'hello world' ]] +then err_exit 'foo bar, where foo is alias for "print hello " failed' +fi +if [[ $(foo \bar) != 'hello bar' ]] +then err_exit 'foo \bar, where foo is alias for "print hello " failed' +fi +alias bar='foo world' +if [[ $(bar) != 'hello world' ]] +then err_exit 'bar, where bar is alias for "foo world" failed' +fi +if [[ $(alias bar) != "bar='foo world'" ]] +then err_exit 'alias bar, where bar is alias for "foo world" failed' +fi +unalias foo || err_exit "unalias foo failed" +alias foo 2> /dev/null && err_exit "alias for non-existent alias foo returns true" +unset bar +alias bar="print foo$bar" +bar=bar +if [[ $(bar) != foo ]] +then err_exit 'alias bar, where bar is alias for "print foo$bar" failed' +fi +unset bar +alias bar='print hello' +if [[ $bar != '' ]] +then err_exit 'alias bar cause variable bar to be set' +fi +alias !!=print +if [[ $(!! hello 2>/dev/null) != hello ]] +then err_exit 'alias for !!=print not working' +fi +alias foo=echo +if [[ $(print "$(foo bar)" ) != bar ]] +then err_exit 'alias in command substitution not working' +fi +( unalias foo) +if [[ $(foo bar 2> /dev/null) != bar ]] +then err_exit 'alias not working after unalias in subshell' +fi +builtin -d rm 2> /dev/null +if whence rm > /dev/null +then [[ ! $(alias -t | grep rm= ) ]] && err_exit 'tracked alias not set' + PATH=$PATH + [[ $(alias -t | grep rm= ) ]] && err_exit 'tracked alias not cleared' +fi +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/append.sh b/usr/src/lib/libshell/common/tests/append.sh new file mode 100644 index 0000000000..7f3cad6021 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/append.sh @@ -0,0 +1,72 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +{ +x=abc +x+=def ;} 2> /dev/null +if [[ $x != abcdef ]] +then err_exit 'abc+def != abcdef' +fi +integer i=3 +{ i+=4;} 2> /dev/null +if (( i != 7 )) +then err_exit '3+4!=7' +fi +iarray=( one two three ) +{ iarray+= (four five six) ;} 2> /dev/null +if [[ ${iarray[@]} != 'one two three four five six' ]] +then err_exit 'index array append fails' +fi +unset iarray +iarray=one +{ iarray+= (four five six) ;} 2> /dev/null +if [[ ${iarray[@]} != 'one four five six' ]] +then err_exit 'index array append to scalar fails' +fi +typeset -A aarray +aarray=( [1]=1 [3]=4 [xyz]=xyz ) +aarray+=( [2]=2 [3]=3 [foo]=bar ) +if [[ ${aarray[3]} != 3 ]] +then err_exit 'associative array append fails' +fi +if [[ ${#aarray[@]} != 5 ]] +then err_exit 'number of elements of associative array append fails' +fi +point=(x=1 y=2) +point+=( y=3 z=4) +if [[ ${point.y} != 3 ]] +then err_exit 'compound append fails' +fi +unset foo +foo=one +foo+=(two) +if [[ ${foo[@]} != 'one two' ]] +then err_exit 'array append to non array variable fails' +fi +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/arith.sh b/usr/src/lib/libshell/common/tests/arith.sh new file mode 100644 index 0000000000..ec3ada5df1 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/arith.sh @@ -0,0 +1,466 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +trap '' FPE # NOTE: osf.alpha requires this (no ieee math) +integer Errors=0 +integer x=1 y=2 z=3 +if (( 2+2 != 4 )) +then err_exit 2+2!=4 +fi +if ((x+y!=z)) +then err_exit x+y!=z +fi +if (($x+$y!=$z)) +then err_exit $x+$y!=$z +fi +if (((x|y)!=z)) +then err_exit "(x|y)!=z" +fi +if ((y >= z)) +then err_exit "y>=z" +fi +if ((y+3 != z+2)) +then err_exit "y+3!=z+2" +fi +if ((y<<2 != 1<<3)) +then err_exit "y<<2!=1<<3" +fi +if ((133%10 != 3)) +then err_exit "133%10!=3" + if (( 2.5 != 2.5 )) + then err_exit 2.5!=2.5 + fi +fi +d=0 +((d || 1)) || err_exit 'd=0; ((d||1))' +if (( d++!=0)) +then err_exit "d++!=0" +fi +if (( --d!=0)) +then err_exit "--d!=0" +fi +if (( (d++,6)!=6 && d!=1)) +then err_exit '(d++,6)!=6 && d!=1' +fi +d=0 +if (( (1?2+1:3*4+d++)!=3 || d!=0)) +then err_exit '(1?2+1:3*4+d++) !=3' +fi +for ((i=0; i < 20; i++)) +do : +done +if (( i != 20)) +then err_exit 'for (( expr)) failed' +fi +for ((i=0; i < 20; i++)); do : ; done +if (( i != 20)) +then err_exit 'for (( expr));... failed' +fi +for ((i=0; i < 20; i++)) do : ; done +if (( i != 20)) +then err_exit 'for (( expr))... failed' +fi +if (( (i?0:1) )) +then err_exit '(( (i?0:1) )) failed' +fi +if (( (1 || 1 && 0) != 1 )) +then err_exit '( (1 || 1 && 0) != 1) failed' +fi +if (( (_=1)+(_x=0)-_ )) +then err_exit '(_=1)+(_x=0)-_ failed' +fi +if (( (3^6) != 5)) +then err_exit '((3^6) != 5) failed' +fi +integer x=1 +if (( (x=-x) != -1 )) +then err_exit '(x=-x) != -1 failed' +fi +i=2 +if (( 1$(($i))3 != 123 )) +then err_exit ' 1$(($i))3 failed' +fi +((pi=4*atan(1.))) +point=( + float x + float y +) +(( point.x = cos(pi/6), point.y = sin(pi/6) )) +if (( point.x*point.x + point.y*point.y > 1.01 )) +then err_exit 'cos*cos +sin*sin > 1.01' +fi +if (( point.x*point.x + point.y*point.y < .99 )) +then err_exit 'cos*cos +sin*sin < .99' +fi +if [[ $((y=x=1.5)) != 1 ]] +then err_exit 'typecast not working in arithmetic evaluation' +fi +typeset -E x=1.5 +( ((x++)) ) 2>/dev/null +if [[ $? == 0 ]] +then err_exit 'postincrement of floating point allowed' +fi +( ((++x)) ) 2>/dev/null +if [[ $? == 0 ]] +then err_exit 'preincrement of floating point allowed' +fi +x=1.5 +( ((x%1.1)) ) 2>/dev/null +if [[ $? == 0 ]] +then err_exit 'floating point allowed with % operator' +fi +x=.125 +if [[ $(( 4 * x/2 )) != 0.25 ]] +then err_exit '(( 4 * x/2 )) is not 0.25, with x=.125' +fi +if [[ $(( pow(2,3) )) != 8 ]] +then err_exit '$(( pow(2,3) )) != 8' +fi +( [[ $(( pow(2,(3)) )) == 8 ]] ) 2> /dev/null +if (( $? )) +then err_exit '$(( pow(2,(3)) )) != 8' +fi +unset x +integer x=1; integer x=1 +if [[ $x != 1 ]] +then err_exit 'two consecutive integer x=1 not working' +fi +unset z +{ z=$(typeset -RZ2 z2; (( z2 = 8 )); print $z2) ;} 2>/dev/null +if [[ $z != "08" ]] +then err_exit "typeset -RZ2 leading 0 decimal not working [z=$z]" +fi +{ z=$(typeset -RZ3 z3; (( z3 = 8 )); print $z3) ;} 2>/dev/null +if [[ $z != "008" ]] +then err_exit "typeset -RZ3 leading 0 decimal not working [z=$z]" +fi +unset z +typeset -Z3 z=010 +(( z=z+1)) +if [[ $z != 011 ]] +then err_exit "leading 0's in -Z not treated as decimal" +fi +unset x +integer x=0 +if [[ $((x+=1)) != 1 ]] || ((x!=1)) +then err_exit "+= not working" + x=1 +fi +x=1 +if [[ $((x*=5)) != 5 ]] || ((x!=5)) +then err_exit "*= not working" + x=5 +fi +if [[ $((x%=4)) != 1 ]] || ((x!=1)) +then err_exit "%= not working" + x=1 +fi +if [[ $((x|=6)) != 7 ]] || ((x!=7)) +then err_exit "|= not working" + x=7 +fi +if [[ $((x&=5)) != 5 ]] || ((x!=5)) +then err_exit "&= not working" + x=5 +fi +function newscope +{ + float x=1.5 + (( x += 1 )) + print -r -- $x +} +if [[ $(newscope) != 2.5 ]] +then err_exit "arithmetic using wrong scope" +fi +unset x +integer y[3]=9 y[4]=2 i=3 +(( x = y[3] + y[4] )) +if [[ $x != 11 ]] +then err_exit "constant index array arithmetic failure" +fi +(( x = $empty y[3] + y[4] )) +if [[ $x != 11 ]] +then err_exit "empty constant index array arithmetic failure" +fi +(( x = y[i] + y[i+1] )) +if [[ $x != 11 ]] +then err_exit "variable subscript index array arithmetic failure" +fi +integer a[5]=3 a[2]=4 +(( x = y[a[5]] + y[a[2]] )) +if [[ $x != 11 ]] +then err_exit "nested subscript index array arithmetic failure" +fi +unset y +typeset -Ai y +y[three]=9 y[four]=2 +three=four +four=three +(( x = y[three] + y[four] )) +if [[ $x != 11 ]] +then err_exit "constant associative array arithmetic failure" +fi +(( x = y[$three] + y[$four] )) +if [[ $x != 11 ]] +then err_exit "variable subscript associative array arithmetic failure" +fi +$SHELL -nc '((a = 1))' 2> /dev/null || err_exit "sh -n fails with arithmetic" +$SHELL -nc '((a.b++))' 2> /dev/null || err_exit "sh -n fails with arithmetic2" +unset z +float z=7.5 +if { (( z%2 != 1));} 2> /dev/null +then err_exit '% not working on floating point' +fi +chr=(a ' ' '=' '\r' '\n' '\\' '\"' '$' "\\'" '[' ']' '(' ')' '<' '\xab' '\040' '`' '{' '}' '*' '\E') +if (('a' == 97)) +then val=(97 32 61 13 10 92 34 36 39 91 93 40 41 60 171 32 96 123 125 42 27) +else val=(129 64 126 13 21 224 127 91 125 173 189 77 93 76 171 32 121 192 208 92 39 21) +fi +q=0 +for ((i=0; i < ${#chr[@]}; i++)) +do if (( '${chr[i]}' != ${val[i]} )) + then err_exit "(( '${chr[i]}' != ${val[i]} ))" + fi + if [[ $(( '${chr[i]}' )) != ${val[i]} ]] + then err_exit "(( '${chr[i]}' )) != ${val[i]}" + fi + if [[ $(( L'${chr[i]}' )) != ${val[i]} ]] + then err_exit "(( '${chr[i]}' )) != ${val[i]}" + fi + if eval '((' "'${chr[i]}'" != ${val[i]} '))' + then err_exit "eval (( '${chr[i]}' != ${val[i]} ))" + fi + if eval '((' "'${chr[i]}'" != ${val[i]} ' + $q ))' + then err_exit "eval (( '${chr[i]}' != ${val[i]} ))" + fi +done +unset x +typeset -ui x=4294967293 +[[ $x != 4294967293 ]] && err_exit "unsigned integers not working" +x=32767 +x=x+1 +[[ $x != 32768 ]] && err_exit "unsigned integer addition not working" +unset x +float x=99999999999999999999999999 +if (( x < 1e20 )) +then err_exit 'large integer constants not working' +fi +unset x y +function foobar +{ + nameref x=$1 + (( x +=1 )) + print $x +} +x=0 y=4 +if [[ $(foobar y) != 5 ]] +then err_exit 'name references in arithmetic statements in functions broken' +fi +if (( 2**3 != pow(2,3) )) +then err_exit '2**3 not working' +fi +if (( 2**3*2 != pow(2,3)*2 )) +then err_exit '2**3*2 not working' +fi +if (( 4**3**2 != pow(4,pow(3,2)) )) +then err_exit '4**3**2 not working' +fi +if (( (4**3)**2 != pow(pow(4,3),2) )) +then err_exit '(4**3)**2 not working' +fi +typeset -Z3 x=11 +typeset -i x +if (( x != 11 )) +then err_exit '-Z3 not treated as decimal' +fi +unset x +typeset -ui x=-1 +(( x >= 0 )) || err_exit 'unsigned integer not working' +(( $x >= 0 )) || err_exit 'unsigned integer not working as $x' +unset x +typeset -ui42 x=50 +if [[ $x != 42#18 ]] +then err_exit 'display of unsigned integers in non-decimal bases wrong' +fi +$SHELL -c 'i=0;(( ofiles[i] != -1 && (ofiles[i] < mins || mins == -1) ));exit 0' 2> /dev/null || err_exit 'lexical error with arithemtic expression' +rm -f core +$SHELL -c '(( +1 == 1))' 2> /dev/null || err_exit 'unary + not working' +typeset -E20 val=123.01234567890 +[[ $val == 123.0123456789 ]] || err_exit "rounding error val=$val" +if [[ $(print x$((10))=foo) != x10=foo ]] +then err_exit 'parsing error with x$((10))=foo' +fi +$SHELL -c 'typeset x$((10))=foo' 2> /dev/null || err_exit 'typeset x$((10)) parse error' +unset x +x=$(( exp(log(2.0)) )) +(( x > 1.999 && x < 2.001 )) || err_exit 'composite functions not working' +unset x y n +typeset -Z8 x=0 y=0 +integer n +for (( n=0; n < 20; n++ )) +do let "x = $x+1" + (( y = $y+1 )) +done +(( x == n )) || err_exit 'let with zero filled fields not working' +(( y == n )) || err_exit '((...)) with zero filled fields not working' +typeset -LZ3 x=10 +[[ $(($x)) == 10 && $((1$x)) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros' +unset y +[[ $(let y=$x;print $y) == 10 && $(let y=1$x;print $y) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros with let' +unset i ip ipx +typeset -i hex=( 172 30 18 1) +typeset -iu ip=0 ipx=0 +integer i +for ((i=0; i < 4; i++)) +do (( ip = (ip<<8) | hex[i])) +done +for ((i=0; i < 4; i++)) +do (( ipx = ip % 256 )) + (( ip /= 256 )) + (( ipx != hex[3-i] )) && err_exit "hex digit $((3-i)) not correct" +done +unset x +x=010 +(( x == 8 )) || err_exit 'leading zeros not treated as octal arithmetic' +(( $x == 8 )) || err_exit 'leading zeros not treated as octal arithmetic with $x' +unset x +typeset -Z x=010 +(( x == 10 )) || err_exit 'leading zeros not ignored for arithmetic' +(( $x == 10 )) || err_exit 'leading zeros not ignored for arithmetic with $x' +typeset -i i=x +(( i == 10 )) || err_exit 'leading zeros not ignored for arithmetic assignment' +(( ${x:0:1} == 0 )) || err_exit 'leading zero should not be stripped for x:a:b' +c010=3 +(( c$x == 3 )) || err_exit 'leading zero with variable should not be stripped' +[[ $( ($SHELL -c '((++1))' 2>&1)2>/dev/null ) == *lvalue* ]] || err_exit "((--1)) not generating error message" +i=2 +(( "22" == 22 )) || err_exit "double quoted constants fail" +(( "2$i" == 22 )) || err_exit "double quoted variables fail" +(( "18+$i+2" == 22 )) || err_exit "double quoted expressions fail" +# 04-04-28 bug fix +unset i; typeset -i i=01-2 +(( i == -1 )) || err_exit "01-2 is not -1" + +trap 'rm -f /tmp/script$$ /tmp/data$$.[12]' EXIT +cat > /tmp/script$$ <<-\! +tests=$* +typeset -A blop +function blop.get +{ + .sh.value=777 +} +function mkobj +{ + nameref obj=$1 + obj=() + [[ $tests == *1* ]] && { + (( obj.foo = 1 )) + (( obj.bar = 2 )) + (( obj.baz = obj.foo + obj.bar )) # ok + echo $obj + } + [[ $tests == *2* ]] && { + (( obj.faz = faz = obj.foo + obj.bar )) # ok + echo $obj + } + [[ $tests == *3* ]] && { + # case 3, 'active' variable involved, w/ intermediate variable + (( obj.foz = foz = ${blop[1]} )) # coredump + echo $obj + } + [[ $tests == *4* ]] && { + # case 4, 'active' variable, in two steps + (( foz = ${blop[1]} )) # ok + (( obj.foz = foz )) # ok + echo $obj + } + [[ $tests == *5* ]] && { + # case 5, 'active' variable involved, w/o intermediate variable + (( obj.fuz = ${blop[1]} )) # coredump + echo $obj + } + [[ $tests == *6* ]] && { + echo $(( obj.baz = obj.foo + obj.bar )) # coredump + } + [[ $tests == *7* ]] && { + echo $(( obj.foo + obj.bar )) # coredump + } +} +mkobj bla +! +chmod +x /tmp/script$$ +[[ $(/tmp/script$$ 1) != '( bar=2 baz=3 foo=1 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed' +[[ $(/tmp/script$$ 2) != '( faz=0 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed' +[[ $(/tmp/script$$ 3) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed' +[[ $(/tmp/script$$ 4) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed' +[[ $(/tmp/script$$ 5) != '( fuz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed' +[[ $(/tmp/script$$ 6) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed' +[[ $(/tmp/script$$ 7) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed' +unset foo +typeset -F1 foo=123456789.19 +[[ $foo == 123456789.2 ]] || err_exit 'typeset -F1 not working correctly' + +# divide by zero + +for expr in '1/(1/2)' '8%(1/2)' '8%(1.0/2)' +do [[ $( ( $SHELL -c "( (($expr)) ) || print ok" ) 2>/dev/null ) == ok ]] || err_exit "divide by zero not trapped: $expr" +done + +for expr in '1/(1.0/2)' '1/(1/2.0)' +do [[ $( ( $SHELL -c "( print -r -- \$(($expr)) )" ) 2>/dev/null ) == 2 ]] || err_exit "invalid value for: $expr" +done +[[ $((5||0)) == 1 ]] || err_exit '$((5||0))'" == $((5||0)) should be 1" +$SHELL -c 'integer x=3 y=2; (( (y += x += 2) == 7 && x==5))' 2> /dev/null || err_exit '((y += x += 2)) not working' +$SHELL -c 'b=0; [[ $((b?a=1:b=9)) == 9 ]]' 2> /dev/null || err_exit 'b?a=1:b=9 not working' +unset x +(( x = 4*atan(1.0) )) +[[ $x == "$((x))" ]] || err_exit '$x !- $((x)) when x is pi' +$SHELL -c "[[ ${x//./} == {14,100}(\d) ]]" 2> /dev/null || err_exit 'pi has less than 14 significant places' +if (( Inf+1 == Inf )) +then [[ $(printf "%g\n" $((Inf))) == inf ]] || err_exit 'printf "%g\n" $((Inf)) fails' +# [[ $(printf "%g\n" $((Nan))) == inf ]] || err_exit 'printf "%g\n" $((Nan)) fails' + [[ $(printf "%g\n" Inf) == inf ]] || err_exit 'printf "%g\n" Inf fails' + [[ $(printf "%g\n" NaN) == nan ]] || err_exit 'printf "%g\n" NaN fails' + [[ $(print -- $((Inf))) == inf ]] || err_exit 'print -- $((Inf)) fails' + (( 1.0/0.0 == Inf )) || err_exit '1.0/0.0 != Inf' + [[ $(print -- $((0.0/0.0))) == nan ]] || err_exit '0.0/0.0 != NaN' + (( Inf*Inf == Inf )) || err_exit 'Inf*Inf != Inf' + (( NaN != NaN )) || err_exit 'NaN == NaN' + (( -5*Inf == -Inf )) || err_exit '-5*Inf != -Inf' + [[ $(print -- $((sqrt(-1.0)))) == nan ]]|| err_exit 'sqrt(-1.0) != NaN' + (( pow(1.0,Inf) == 1.0 )) || err_exit 'pow(1.0,Inf) != 1.0' + (( pow(Inf,0.0) == 1.0 )) || err_exit 'pow(Inf,0.0) != 1.0' + [[ $(print -- $((NaN/Inf))) == nan ]] || err_exit 'NaN/Inf != NaN' + (( 4.0/Inf == 0.0 )) || err_exit '4.0/Inf != 0.0' +else err_exit 'Inf and NaN not working' +fi +unset x y +float x=14.555 y +y=$(printf "%a" x) +(( x == y )) || err_exit "output of printf %a not self preserving -- expected $x, got $y" +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/arrays.sh b/usr/src/lib/libshell/common/tests/arrays.sh new file mode 100644 index 0000000000..7dd09fca0f --- /dev/null +++ b/usr/src/lib/libshell/common/tests/arrays.sh @@ -0,0 +1,381 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +function fun +{ + integer i + unset xxx + for i in 0 1 + do xxx[$i]=$i + done +} + +Command=${0##*/} +integer Errors=0 +set -A x zero one two three four 'five six' +if [[ $x != zero ]] +then err_exit '$x is not element 0' +fi +if [[ ${x[0]} != zero ]] +then err_exit '${x[0] is not element 0' +fi +if (( ${#x[0]} != 4 )) +then err_exit "length of ${x[0]} is not 4" +fi +if (( ${#x[@]} != 6 )) +then err_exit 'number of elements of x is not 6' +fi +if [[ ${x[2]} != two ]] +then err_exit ' element two is not 2' +fi +if [[ ${x[@]:2:1} != two ]] +then err_exit ' ${x[@]:2:1} is not two' +fi +set -A y -- ${x[*]} +if [[ $y != zero ]] +then err_exit '$x is not element 0' +fi +if [[ ${y[0]} != zero ]] +then err_exit '${y[0] is not element 0' +fi +if (( ${#y[@]} != 7 )) +then err_exit 'number of elements of y is not 7' +fi +if [[ ${y[2]} != two ]] +then err_exit ' element two is not 2' +fi +set +A y nine ten +if [[ ${y[2]} != two ]] +then err_exit ' element two is not 2' +fi +if [[ ${y[0]} != nine ]] +then err_exit '${y[0] is not nine' +fi +unset y[4] +if (( ${#y[@]} != 6 )) +then err_exit 'number of elements of y is not 6' +fi +if (( ${#y[4]} != 0 )) +then err_exit 'string length of unset element is not 0' +fi +unset foo +if (( ${#foo[@]} != 0 )) +then err_exit 'number of elements of unset variable foo is not 0' +fi +foo='' +if (( ${#foo[0]} != 0 )) +then err_exit 'string length of null element is not 0' +fi +if (( ${#foo[@]} != 1 )) +then err_exit 'number of elements of null variable foo is not 1' +fi +unset foo +foo[0]=foo +foo[3]=bar +unset foo[0] +unset foo[3] +if (( ${#foo[@]} != 0 )) +then err_exit 'number of elements of left in variable foo is not 0' +fi +unset foo +foo[3]=bar +foo[0]=foo +unset foo[3] +unset foo[0] +if (( ${#foo[@]} != 0 )) +then err_exit 'number of elements of left in variable foo again is not 0' +fi +fun +if (( ${#xxx[@]} != 2 )) +then err_exit 'number of elements of left in variable xxx is not 2' +fi +fun +if (( ${#xxx[@]} != 2 )) +then err_exit 'number of elements of left in variable xxx again is not 2' +fi +set -A foo -- "${x[@]}" +if (( ${#foo[@]} != 6 )) +then err_exit 'number of elements of foo is not 6' +fi +if (( ${#PWD[@]} != 1 )) +then err_exit 'number of elements of PWD is not 1' +fi +unset x +x[2]=foo x[4]=bar +if (( ${#x[@]} != 2 )) +then err_exit 'number of elements of x is not 2' +fi +s[1]=1 c[1]=foo +if [[ ${c[s[1]]} != foo ]] +then err_exit 'c[1]=foo s[1]=1; ${c[s[1]]} != foo' +fi +unset s +typeset -Ai s +y=* z=[ +s[$y]=1 +s[$z]=2 +if (( ${#s[@]} != 2 )) +then err_exit 'number of elements of is not 2' +fi +(( s[$z] = s[$z] + ${s[$y]} )) +if [[ ${s[$z]} != 3 ]] +then err_exit '[[ ${s[$z]} != 3 ]]' +fi +if (( s[$z] != 3 )) +then err_exit '(( s[$z] != 3 ))' +fi +(( s[$y] = s[$y] + ${s[$z]} )) +if [[ ${s[$y]} != 4 ]] +then err_exit '[[ ${s[$y]} != 4 ]]' +fi +if (( s[$y] != 4 )) +then err_exit '(( s[$y] != 4 ))' +fi +unset y +set -A y 2 4 6 +typeset -i y +z=${y[@]} +typeset -R12 y +typeset -i y +if [[ ${y[@]} != "$z" ]] +then err_exit 'error in array conversion from int to R12' +fi +if (( ${#y[@]} != 3 )) +then err_exit 'error in count of array conversion from int to R12' +fi +unset abcdefg +: ${abcdefg[1]} +set | grep '^abcdefg$' >/dev/null && err_exit 'empty array variable in set list' +unset x y +x=1 +typeset -i y[$x]=4 +if [[ ${y[1]} != 4 ]] +then err_exit 'arithmetic expressions in typeset not working' +fi +unset foo +typeset foo=bar +typeset -A foo +if [[ ${foo[0]} != bar ]] +then err_exit 'initial value not preserved when typecast to associative' +fi +unset foo +foo=(one two) +typeset -A foo +foo[two]=3 +if [[ ${#foo[*]} != 3 ]] +then err_exit 'conversion of indexed to associative array failed' +fi +set a b c d e f g h i j k l m +if [[ ${#} != 13 ]] +then err_exit '${#} not 13' +fi +unset xxx +xxx=foo +if [[ ${!xxx[@]} != 0 ]] +then err_exit '${!xxx[@]} for scalar not 0' +fi +if [[ ${11} != k ]] +then err_exit '${11} not working' +fi +if [[ ${@:4:1} != d ]] +then err_exit '${@:4:1} not working' +fi +foovar1=abc +foovar2=def +if [[ ${!foovar@} != +(foovar[[:alnum:]]?([ ])) ]] +then err_exit '${!foovar@} does not expand correctly' +fi +if [[ ${!foovar1} != foovar1 ]] +then err_exit '${!foovar1} != foovar1' +fi +unset xxx +: ${xxx[3]} +if [[ ${!xxx[@]} ]] +then err_exit '${!xxx[@]} should be null' +fi +integer i=0 +{ + set -x + xxx[++i]=1 + set +x +} 2> /dev/null +if (( i != 1)) +then err_exit 'execution trace side effects with array subscripts' +fi +unset list +: $(set -A list foo bar) +if (( ${#list[@]} != 0)) +then err_exit '$(set -A list ...) leaves side effects' +fi +unset list +list= (foo bar bam) +( set -A list one two three four) +if [[ ${list[1]} != bar ]] +then err_exit 'array not restored after subshell' +fi +XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin +xpath=( $( IFS=: ; echo $XPATH ) ) +if [[ $(print -r "${xpath[@]##*/}") != 'bin bin ucb bin . sbin sbin' ]] +then err_exit '${xpath[@]##*/} not applied to each element' +fi +foo=( zero one '' three four '' six) +integer n=-1 +if [[ ${foo[@]:n} != six ]] +then err_exit 'array offset of -1 not working' +fi +if [[ ${foo[@]: -3:1} != four ]] +then err_exit 'array offset of -3:1 not working' +fi +$SHELL -c 'x=(if then else fi)' 2> /dev/null || err_exit 'reserved words in x=() assignment not working' +unset foo +foo=one +foo=( $foo two) +if [[ ${#foo[@]} != 2 ]] +then err_exit 'array getting unset before right hand side evaluation' +fi +foo=(143 3643 38732) +export foo +typeset -i foo +if [[ $($SHELL -c 'print $foo') != 143 ]] +then err_exit 'exporting indexed array not exporting 0-th element' +fi +( $SHELL -c ' + unset foo + typeset -A foo=([0]=143 [1]=3643 [2]=38732) + export foo + typeset -i foo + [[ $($SHELL -c "print $foo") == 143 ]]' +) 2> /dev/null || + err_exit 'exporting associative array not exporting 0-th element' +unset foo +typeset -A foo +foo[$((10))]=ok 2> /dev/null || err_exit 'arithmetic expression as subscript not working' +unset foo +typeset -A foo +integer foo=0 +[[ $foo == 0 ]] || err_exit 'zero element of associative array not being set' +unset foo +typeset -A foo=( [two]=1) +for i in one three four five +do : ${foo[$i]} +done +if [[ ${!foo[@]} != two ]] +then err_exit 'Error in subscript names' +fi +unset x +x=( 1 2 3) +(x[1]=8) +[[ ${x[1]} == 2 ]] || err_exit 'index array produce side effects in subshells' +x=( 1 2 3) +( + x+=(8) + [[ ${#x[@]} == 4 ]] || err_exit 'index array append in subshell error' +) +[[ ${#x[@]} == 3 ]] || err_exit 'index array append in subshell effects parent' +x=( [one]=1 [two]=2 [three]=3) +(x[two]=8) +[[ ${x[two]} == 2 ]] || err_exit 'associative array produce side effects in subshells' +unset x +x=( [one]=1 [two]=2 [three]=3) +( + x+=( [four]=4 ) + [[ ${#x[@]} == 4 ]] || err_exit 'associative array append in subshell error' +) +[[ ${#x[@]} == 3 ]] || err_exit 'associative array append in subshell effects parent' +unset x +integer i +for ((i=0; i < 40; i++)) +do x[i]=$i +done +[[ ${#x[@]} == 40 ]] || err_exit 'index arrays loosing values' +[[ $( ($SHELL -c 'typeset -A var; (IFS=: ; set -A var a:b:c ;print ${var[@]});:' )2>/dev/null) == 'a b c' ]] || err_exit 'change associative to index failed' +unset foo +[[ $(foo=good +for ((i=0; i < 2; i++)) +do [[ ${foo[i]} ]] && print ok +done) == ok ]] || err_exit 'invalid optimization for subscripted variables' +( +x=([foo]=bar) +set +A x bam +) 2> /dev/null && err_exit 'set +A with associative array should be an error' +unset bam foo +foo=0 +typeset -A bam +unset bam[foo] +bam[foo]=value +[[ $bam == value ]] && err_exit 'unset associative array element error' +: only first element of an array can be exported +unset bam +trap 'rm -f /tmp/sharr$$' EXIT +print 'print ${var[0]} ${var[1]}' > /tmp/sharr$$ +chmod +x /tmp/sharr$$ +[[ $($SHELL -c "var=(foo bar);export var;/tmp/sharr$$") == foo ]] || err_exit 'export array not exporting just first element' +unset foo +set -o allexport +foo=one +foo[1]=two +foo[0]=three +[[ $foo == three ]] || err_exit 'export all not working with arrays' +cat > /tmp/sharr$$ <<- \! + typeset -A foo + print foo${foo[abc]} +! +# 04-05-24 bug fix +unset foo +[[ $($SHELL -c "typeset -A foo;/tmp/sharr$$") == foo ]] 2> /dev/null || err_exit 'empty associative arrays not being cleared correctly before scripts' +[[ $($SHELL -c "typeset -A foo;foo[abc]=abc;/tmp/sharr$$") == foo ]] 2> /dev/null || err_exit 'associative arrays not being cleared correctly before scripts' +unset foo +foo=(one two) +[[ ${foo[@]:1} == two ]] || err_exit '${foo[@]:1} == two' +[[ ! ${foo[@]:2} ]] || err_exit '${foo[@]:2} not null' +unset foo +foo=one +[[ ! ${foo[@]:1} ]] || err_exit '${foo[@]:1} not null' +function EMPTY +{ + typeset i + typeset -n ARRAY=$1 + for i in ${!ARRAY[@]} + do unset ARRAY[$i] + done +} +unset foo +typeset -A foo +foo[bar]=bam +foo[x]=y +EMPTY foo +[[ $(typeset | grep foo$) == *associative* ]] || err_exit 'array lost associative attribute' +[[ ! ${foo[@]} ]] || err_exit 'array not empty' +[[ ! ${!foo[@]} ]] || err_exit 'array names not empty' +unset foo +foo=bar +set -- "${foo[@]:1}" +(( $# == 0 )) || err_exit '${foo[@]:1} should not have any values' +unset bar +: ${_foo[bar=4]} +(( bar == 4 )) || err_exit 'subscript of unset variable not evaluated' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/attributes.sh b/usr/src/lib/libshell/common/tests/attributes.sh new file mode 100644 index 0000000000..8be16f1d42 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/attributes.sh @@ -0,0 +1,216 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +r=readonly u=Uppercase l=Lowercase i=22 i8=10 L=abc L5=def uL5=abcdef xi=20 +x=export t=tagged H=hostname LZ5=026 RZ5=026 Z5=123 lR5=ABcdef R5=def n=l +for option in u l i i8 L L5 LZ5 RZ5 Z5 r x H t R5 uL5 lR5 xi n +do typeset -$option $option +done +(r=newval) 2> /dev/null && err_exit readonly attribute fails +i=i+5 +if ((i != 27)) +then err_exit integer attributes fails +fi +if [[ $i8 != 8#12 ]] +then err_exit integer base 8 fails +fi +if [[ $u != UPPERCASE ]] +then err_exit uppercase fails +fi +if [[ $l != lowercase ]] +then err_exit lowercase fails +fi +if [[ $n != lowercase ]] +then err_exit reference variables fail +fi +if [[ t=tagged != $(typeset -t) ]] +then err_exit tagged fails +fi +if [[ t != $(typeset +t) ]] +then err_exit tagged fails +fi +if [[ $Z5 != 00123 ]] +then err_exit zerofill fails +fi +if [[ $RZ5 != 00026 ]] +then err_exit right zerofill fails +fi +L=12345 +if [[ $L != 123 ]] +then err_exit leftjust fails +fi +if [[ $L5 != "def " ]] +then err_exit leftjust fails +fi +if [[ $uL5 != ABCDE ]] +then err_exit leftjust uppercase fails +fi +if [[ $lR5 != bcdef ]] +then err_exit rightjust fails +fi +if [[ $R5 != " def" ]] +then err_exit rightjust fails +fi +if [[ $($SHELL -c 'echo $x') != export ]] +then err_exit export fails +fi +if [[ $($SHELL -c 'xi=xi+4;echo $xi') != 24 ]] +then err_exit export attributes fails +fi +x=$(foo=abc $SHELL <<! + foo=bar + $SHELL -c 'print \$foo' +! +) +if [[ $x != bar ]] +then err_exit 'environment variables require re-export' +fi +(typeset + ) > /dev/null 2>&1 || err_exit 'typeset + not working' +(typeset -L-5 buf="A" 2>/dev/null) +if [[ $? == 0 ]] +then err_exit 'typeset allows negative field for left/right adjust' +fi +a=b +readonly $a=foo +if [[ $b != foo ]] +then err_exit 'readonly $a=b not working' +fi +if [[ $(export | grep '^PATH=') != PATH=* ]] +then err_exit 'export not working' +fi +picture=( + bitmap=/fruit + size=(typeset -E x=2.5) +) +string="$(print $picture)" +if [[ "${string}" != *'size=( typeset -E'* ]] +then err_exit 'print of compound exponential variable not working' +fi +sz=(typeset -E y=2.2) +string="$(print $sz)" +if [[ "${sz}" == *'typeset -E -F'* ]] +then err_exit 'print of exponential shows both -E and -F attributes' +fi +print 'typeset -i m=48/4+1;print -- $m' > /tmp/ksh$$ +chmod +x /tmp/ksh$$ +typeset -Z2 m +if [[ $(/tmp/ksh$$) != 13 ]] +then err_exit 'attributes not cleared for script execution' +fi +typeset -Z LAST=00 +unset -f foo +function foo +{ + if [[ $1 ]] + then LAST=$1 + else ((LAST++)) + fi +} +foo 1 +if (( ${#LAST} != 2 )) +then err_exit 'LAST!=2' +fi +foo +if (( ${#LAST} != 2 )) +then err_exit 'LAST!=2' +fi +rm -rf /tmp/ksh$$ +set -a +unset foo +foo=bar +if [[ $(export | grep ^foo=) != 'foo=bar' ]] +then err_exit 'all export not working' +fi +unset foo +read foo <<! +bar +! +if [[ $(export | grep ^foo=) != 'foo=bar' ]] +then err_exit 'all export not working with read' +fi +if [[ $(typeset | grep PS2) == PS2 ]] +then err_exit 'typeset without arguments outputs names without attributes' +fi +unset a z q x +w1=hello +w2=world +t1="$w1 $w2" +if (( 'a' == 97 )) +then b1=aGVsbG8gd29ybGQ= + b2=aGVsbG8gd29ybGRoZWxsbyB3b3JsZA== +else b1=iIWTk5ZAppaZk4Q= + b2=iIWTk5ZAppaZk4SIhZOTlkCmlpmThA== +fi +z=$b1 +typeset -b x=$b1 +[[ $x == "$z" ]] || print -u2 'binary variable not expanding correctly' +[[ $(printf "%B" x) == $t1 ]] || err_exit 'typeset -b not working' +typeset -b -Z5 a=$b1 +[[ $(printf "%B" a) == $w1 ]] || err_exit 'typeset -b -Z5 not working' +typeset -b q=$x$x +[[ $q == $b2 ]] || err_exit 'typeset -b not working with concatination' +[[ $(printf "%B" q) == $t1$t1 ]] || err_exit 'typeset -b concatination not working' +x+=$b1 +[[ $x == $b2 ]] || err_exit 'typeset -b not working with append' +[[ $(printf "%B" x) == $t1$t1 ]] || err_exit 'typeset -b append not working' +typeset -b -Z20 z=$b1 +(( $(printf "%B" z | wc -c) == 20 )) || err_exit 'typeset -b -Z20 not storing 20 bytes' +{ + typeset -b v1 v2 + read -N11 v1 + read -N22 v2 +} << ! +hello worldhello worldhello world +! +[[ $v1 == "$b1" ]] || err_exit "v1=$v1 should be $b1" +[[ $v2 == "$x" ]] || err_exit "v1=$v2 should be $x" +[[ $(env '!=1' $SHELL -c 'echo ok' 2>/dev/null) == ok ]] || err_exit 'malformed environment terminates shell' +unset var +typeset -b var +printf '12%Z34' | read -r -N 5 var +[[ $var == MTIAMzQ= ]] || err_exit 'binary files with zeros not working' +unset var +if command typeset -usi var=0xfffff 2> /dev/null +then (( $var == 0xffff )) || err_exit 'unsigned short integers not working' +else err_exit 'typeset -usi cannot be used for unsigned short' +fi +[[ $($SHELL -c 'unset foo;typeset -Z2 foo; print ${foo:-3}' 2> /dev/null) == 3 ]] || err_exit '${foo:-3} not 3 when typeset -Z2 field undefined' +[[ $($SHELL -c 'unset foo;typeset -Z2 foo; print ${foo:=3}' 2> /dev/null) == 03 ]] || err_exit '${foo:=-3} not 3 when typeset -Z2 foo undefined' +unset foo bar +unset -f fun +function fun +{ + export foo=hello + typeset -x bar=world + [[ $foo == hello ]] || err_exit 'export scoping problem in function' +} +fun +[[ $(export | grep foo) == 'foo=hello' ]] || err_exit 'export not working in functions' +[[ $(export | grep bar) ]] && err_exit 'typeset -x not local' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/basic.sh b/usr/src/lib/libshell/common/tests/basic.sh new file mode 100644 index 0000000000..28755da226 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/basic.sh @@ -0,0 +1,336 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +# test basic file operations like redirection, pipes, file expansion +Command=${0##*/} +integer Errors=0 +umask u=rwx,go=rx || err_exit "umask u=rws,go=rx failed" +if [[ $(umask -S) != u=rwx,g=rx,o=rx ]] +then err_exit 'umask -S incorrect' +fi +mkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed" +trap "cd /; rm -rf /tmp/ksh$$" EXIT +pwd=$PWD +[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL +cd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed" +# optimizer bug test +> foobar +for i in 1 2 +do print foobar* + rm -f foobar +done > out$$ +if [[ "$(<out$$)" != "foobar"$'\n'"foobar*" ]] +then print -u2 "optimizer bug with file expansion" +fi +rm -f out$$ foobar +mkdir dir +if [[ $(print */) != dir/ ]] +then err_exit 'file expansion with trailing / not working' +fi +if [[ $(print *) != dir ]] +then err_exit 'file expansion with single file not working' +fi +print hi > .foo +if [[ $(print *) != dir ]] +then err_exit 'file expansion leading . not working' +fi +date > dat1 || err_exit "date > dat1 failed" +test -r dat1 || err_exit "dat1 is not readable" +x=dat1 +cat <$x > dat2 || err_exit "cat < $x > dat2 failed" +cat dat1 dat2 | cat | cat | cat > dat3 || err_exit "cat pipe failed" +cat > dat4 <<! +$(date) +! +cat dat1 dat2 | cat | cat | cat > dat5 & +wait $! +set -- dat* +if (( $# != 5 )) +then err_exit "dat* matches only $# files" +fi +if (command > foo\\abc) 2> /dev/null +then set -- foo* + if [[ $1 != 'foo\abc' ]] + then err_exit 'foo* does not match foo\abc' + fi +fi +if ( : > TT* && : > TTfoo ) 2>/dev/null +then set -- TT* + if (( $# < 2 )) + then err_exit 'TT* not expanding when file TT* exists' + fi +fi +cd ~- || err_exit "cd back failed" +cat > /tmp/ksh$$/script <<- ! + #! $SHELL + print -r -- \$0 +! +chmod 755 /tmp/ksh$$/script +if [[ $(/tmp/ksh$$/script) != "/tmp/ksh$$/script" ]] +then err_exit '$0 not correct for #! script' +fi +rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed" +bar=foo +eval foo=\$bar +if [[ $foo != foo ]] +then err_exit 'eval foo=\$bar not working' +fi +bar='foo=foo\ bar' +eval $bar +if [[ $foo != 'foo bar' ]] +then err_exit 'eval foo=\$bar, with bar="foo\ bar" not working' +fi +cd /tmp +cd ../../tmp || err_exit "cd ../../tmp failed" +if [[ $PWD != /tmp ]] +then err_exit 'cd ../../tmp is not /tmp' +fi +( sleep 2; cat <<! +foobar +! +) | cat > /tmp/foobar$$ & +wait $! +foobar=$( < /tmp/foobar$$) +if [[ $foobar != foobar ]] +then err_exit "$foobar is not foobar" +fi +{ + print foo + /bin/echo bar + print bam +} > /tmp/foobar$$ +if [[ $( < /tmp/foobar$$) != $'foo\nbar\nbam' ]] +then err_exit "Output file pointer not shared correctly." +fi +cat > /tmp/foobar$$ <<\! + print foo + /bin/echo bar + print bam +! +chmod +x /tmp/foobar$$ +if [[ $(/tmp/foobar$$) != $'foo\nbar\nbam' ]] +then err_exit "Script not working." +fi +if [[ $(/tmp/foobar$$ | /bin/cat) != $'foo\nbar\nbam' ]] +then err_exit "Script | cat not working." +fi +if [[ $( /tmp/foobar$$) != $'foo\nbar\nbam' ]] +then err_exit "Output file pointer not shared correctly." +fi +rm -f /tmp/foobar$$ +x=$( (print foo) ; (print bar) ) +if [[ $x != $'foo\nbar' ]] +then err_exit " ( (print foo);(print bar ) failed" +fi +x=$( (/bin/echo foo) ; (print bar) ) +if [[ $x != $'foo\nbar' ]] +then err_exit " ( (/bin/echo);(print bar ) failed" +fi +x=$( (/bin/echo foo) ; (/bin/echo bar) ) +if [[ $x != $'foo\nbar' ]] +then err_exit " ( (/bin/echo);(/bin/echo bar ) failed" +fi +cat > /tmp/ksh$$ <<\! +if [[ -p /dev/fd/0 ]] +then builtin cat + cat - > /dev/null + [[ -p /dev/fd/0 ]] && print ok +else print no +fi +! +chmod +x /tmp/ksh$$ +case $( (print) | /tmp/ksh$$;:) in +ok) ;; +no) err_exit "[[ -p /dev/fd/0 ]] fails for standard input pipe" ;; +*) err_exit "builtin replaces standard input pipe" ;; +esac +print 'print $0' > /tmp/ksh$$ +print ". /tmp/ksh$$" > /tmp/ksh$$x +chmod +x /tmp/ksh$$x +if [[ $(/tmp/ksh$$x) != /tmp/ksh$$x ]] +then err_exit '$0 not correct for . script' +fi +rm -r /tmp/ksh$$ /tmp/ksh$$x +mkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed" +cd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed" +print ./b > ./a; print ./c > b; print ./d > c; print ./e > d; print "echo \"hello there\"" > e +chmod 755 a b c d e +x=$(./a) +if [[ $x != "hello there" ]] +then err_exit "nested scripts failed" +fi +x=$( (./a) | cat) +if [[ $x != "hello there" ]] +then err_exit "scripts in subshells fail" +fi +cd ~- || err_exit "cd back failed" +rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed" +x=$( (/bin/echo foo) 2> /dev/null ) +if [[ $x != foo ]] +then err_exit "subshell in command substitution fails" +fi +exec 1>&- +x=$(print hello) +if [[ $x != hello ]] +then err_exit "command subsitution with stdout closed failed" +fi +cd $pwd +x=$(cat <<\! | $SHELL +/bin/echo | /bin/cat +/bin/echo hello +! +) +if [[ $x != $'\n'hello ]] +then err_exit "$SHELL not working when standard input is a pipe" +fi +x=$( (/bin/echo hello) 2> /dev/null ) +if [[ $x != hello ]] +then err_exit "subshell in command substitution with 1 closed fails" +fi +cat > /tmp/ksh$$ <<- \! +read line 2> /dev/null +print done +! +if [[ $($SHELL /tmp/ksh$$ <&-) != done ]] +then err_exit "executing script with 0 closed fails" +fi +trap '' INT +cat > /tmp/ksh$$ <<- \! +trap 'print bad' INT +kill -s INT $$ +print good +! +chmod +x /tmp/ksh$$ +if [[ $($SHELL /tmp/ksh$$) != good ]] +then err_exit "traps ignored by parent not ignored" +fi +trap - INT +cat > /tmp/ksh$$ <<- \! +read line +/bin/cat +! +if [[ $($SHELL /tmp/ksh$$ <<! +one +two +! +) != two ]] +then err_exit "standard input not positioned correctly" +fi +word=$(print $'foo\nbar' | { read line; /bin/cat;}) +if [[ $word != bar ]] +then err_exit "pipe to { read line; /bin/cat;} not working" +fi +word=$(print $'foo\nbar' | ( read line; /bin/cat) ) +if [[ $word != bar ]] +then err_exit "pipe to ( read line; /bin/cat) not working" +fi +if [[ $(print x{a,b}y) != 'xay xby' ]] +then err_exit 'brace expansion not working' +fi +if [[ $(for i in foo bar + do ( tgz=$(print $i) + print $tgz) + done) != $'foo\nbar' ]] +then err_exit 'for loop subshell optimizer bug' +fi +unset a1 +optbug() +{ + set -A a1 foo bar bam + integer i + for ((i=0; i < 3; i++)) + do + (( ${#a1[@]} < 2 )) && return 0 + set -- "${a1[@]}" + shift + set -A a1 -- "$@" + done + return 1 +} +optbug || err_exit 'array size optimzation bug' +wait # not running --pipefile which would interfere with subsequent tests +: $(jobs -p) # required to clear jobs for next jobs -p (interactive side effect) +sleep 20 & +if [[ $(jobs -p) != $! ]] +then err_exit 'jobs -p not reporting a background job' +fi +sleep 20 & +foo() +{ + set -- $(jobs -p) + (( $# == 2 )) || err_exit "$# jobs not reported -- 2 expected" +} +foo +[[ $( (trap 'print alarm' ALRM; sleep 4) & sleep 2; kill -ALRM $!) == alarm ]] || err_exit 'ALRM signal not working' +[[ $($SHELL -c 'trap "" HUP; $SHELL -c "(sleep 2;kill -HUP $$)& sleep 4;print done"') != done ]] && err_exit 'ignored traps not being ignored' +[[ $($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' +command exec 3<> /dev/null +if cat /dev/fd/3 >/dev/null 2>&1 +then [[ $($SHELL -c 'cat <(print foo)' 2> /dev/null) == foo ]] || err_exit 'process substitution not working' + [[ $($SHELL -c 'print $(cat <(print foo) )' 2> /dev/null) == foo ]] || err_exit 'process substitution in subshell not working' + [[ $($SHELL -c $'tee >(grep \'1$\' > /tmp/ksh'$$'x) > /dev/null <<- \!!! + line0 + line1 + line2 + !!! + wait + cat /tmp/ksh'$$x 2> /dev/null) == line1 ]] || err_exit '>() process substitution fails' + > /tmp/ksh$$x + [[ $($SHELL -c $' + for i in 1 + do tee >(grep \'1$\' > /tmp/ksh'$$'x) > /dev/null <<- \!!! + line0 + line1 + line2 + !!! + done + wait + cat /tmp/ksh'$$x 2>> /dev/null) == line1 ]] || err_exit '>() process substitution fails in for loop' + [[ $({ $SHELL -c 'cat <(for i in x y z; do print $i; done)';} 2> /dev/null) == $'x\ny\nz' ]] || + err_exit 'process substitution of compound commands not working' +fi +[[ $($SHELL -r 'command -p :' 2>&1) == *restricted* ]] || err_exit 'command -p not restricted' +print cat > /tmp/ksh$$x +chmod +x /tmp/ksh$$x +[[ $($SHELL -c "print foo | /tmp/ksh$$x ;:" 2> /dev/null ) == foo ]] || err_exit 'piping into script fails' +[[ $($SHELL -c 'X=1;print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 1 ]] || err_exit 'x=1;${x:=$(..."...")} failure' +[[ $($SHELL -c 'print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 0 ]] || err_exit '${x:=$(..."...")} failure' +if [[ -d /dev/fd && -w /dev/fd/3 ]] +then [[ $(cat <(print hello) ) == hello ]] || err_exit "process substitution not working outside for or while loop" + $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" +fi +exec 3> /dev/null +print 'print foo "$@"' > /tmp/ksh$$x +[[ $( print "(/tmp/ksh$$x bar)" | $SHELL 2>/dev/null) == 'foo bar' ]] || err_exit 'script pipe to shell fails' +print "#! $SHELL" > /tmp/ksh$$x +print 'print -- $0' >> /tmp/ksh$$x +chmod +x /tmp/ksh$$x +[[ $(/tmp/ksh$$x) == /tmp/ksh$$x ]] || err_exit "\$0 is $0 instead of /tmp/ksh$$x" +rm -f /tmp/ksh$$x +exec 3<&- +( typeset -r foo=bar) 2> /dev/null || err_exit 'readonly variables set in a subshell cannot unset' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/bracket.sh b/usr/src/lib/libshell/common/tests/bracket.sh new file mode 100644 index 0000000000..25daf72c32 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/bracket.sh @@ -0,0 +1,233 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +null='' +if [[ ! -z $null ]] +then err_exit "-z: null string should be of zero length" +fi +file=/tmp/regress$$ +if [[ -z $file ]] +then err_exit "-z: $file string should not be of zero length" +fi +trap "rm -f $file" EXIT +rm -f $file +if [[ -a $file ]] +then err_exit "-a: $file shouldn't exist" +fi +> $file +if [[ ! -a $file ]] +then err_exit "-a: $file should exist" +fi +chmod 777 $file +if [[ ! -r $file ]] +then err_exit "-r: $file should be readable" +fi +if [[ ! -w $file ]] +then err_exit "-w: $file should be writable" +fi +if [[ ! -w $file ]] +then err_exit "-x: $file should be executable" +fi +if [[ ! -w $file || ! -r $file ]] +then err_exit "-rw: $file should be readable/writable" +fi +if [[ -s $file ]] +then err_exit "-s: $file should be of zero size" +fi +if [[ ! -f $file ]] +then err_exit "-f: $file should be an ordinary file" +fi +if [[ -d $file ]] +then err_exit "-f: $file should not be a directory file" +fi +if [[ ! -d . ]] +then err_exit "-d: . should not be a directory file" +fi +if [[ -f /dev/null ]] +then err_exit "-f: /dev/null should not be an ordinary file" +fi +chmod 000 $file +if [[ -r $file ]] +then err_exit "-r: $file should not be readable" +fi +if [[ ! -O $file ]] +then err_exit "-r: $file should be owned by me" +fi +if [[ -w $file ]] +then err_exit "-w: $file should not be writable" +fi +if [[ -w $file ]] +then err_exit "-x: $file should not be executable" +fi +if [[ -w $file || -r $file ]] +then err_exit "-rw: $file should not be readable/writable" +fi +if [[ -z x && -z x || ! -z x ]] +then : +else err_exit " wrong precedence" +fi +if [[ -z x && (-z x || ! -z x) ]] +then err_exit " () grouping not working" +fi +if [[ foo < bar ]] +then err_exit "foo comes before bar" +fi +[[ . -ef $(pwd) ]] || err_exit ". is not $PWD" +set -o allexport +[[ -o allexport ]] || err_exit '-o: did not set allexport option' +if [[ -n $null ]] +then err_exit "'$null' has non-zero length" +fi +if [[ ! -r /dev/fd/0 ]] +then err_exit "/dev/fd/0 not open for reading" +fi +if [[ ! -w /dev/fd/2 ]] +then err_exit "/dev/fd/2 not open for writing" +fi +sleep 1 +if [[ ! . -ot $file ]] +then err_exit ". should be older than $file" +fi +if [[ /bin -nt $file ]] +then err_exit "$file should be newer than /bin" +fi +if [[ $file != /tmp/* ]] +then err_exit "$file should match /tmp/*" +fi +if [[ $file = '/tmp/*' ]] +then err_exit "$file should not equal /tmp/*" +fi +[[ ! ( ! -z $null && ! -z x) ]] || err_exit "negation and grouping" +[[ -z '' || -z '' || -z '' ]] || err_exit "three ors not working" +[[ -z '' && -z '' && -z '' ]] || err_exit "three ors not working" +(exit 8) +if [[ $? -ne 8 || $? -ne 8 ]] +then err_exit 'value $? within [[...]]' +fi +x='(x' +if [[ '(x' != '('* ]] +then err_exit " '(x' does not match '('* within [[...]]" +fi +if [[ '(x' != "("* ]] +then err_exit ' "(x" does not match "("* within [[...]]' +fi +if [[ '(x' != \(* ]] +then err_exit ' "(x" does not match \(* within [[...]]' +fi +if [[ 'x(' != *'(' ]] +then err_exit " 'x(' does not match '('* within [[...]]" +fi +if [[ 'x&' != *'&' ]] +then err_exit " 'x&' does not match '&'* within [[...]]" +fi +if [[ 'xy' = *'*' ]] +then err_exit " 'xy' matches *'*' within [[...]]" +fi +if [[ 3 > 4 ]] +then err_exit '3 < 4' +fi +if [[ 4 < 3 ]] +then err_exit '3 > 4' +fi +if [[ 3x > 4x ]] +then err_exit '3x < 4x' +fi +x='bin|dev|?' +cd / +if [[ $(print $x) != "$x" ]] +then err_exit 'extended pattern matching on command arguments' +fi +if [[ dev != $x ]] +then err_exit 'extended pattern matching not working on variables' +fi +if [[ -u $SHELL ]] +then err_exit "setuid on $SHELL" +fi +if [[ -g $SHELL ]] +then err_exit "setgid on $SHELL" +fi +test -d . -a '(' ! -f . ')' || err_exit 'test not working' +if [[ '!' != ! ]] +then err_exit 'quoting unary operator not working' +fi +chmod 600 $file +exec 4> $file +print -u4 foobar +if [[ ! -s $file ]] +then err_exit "-s: $file should be non-zero" +fi +exec 4>&- +if [[ 011 -ne 11 ]] +then err_exit "leading zeros in arithmetic compares not ignored" +fi +{ + set -x + [[ foo > bar ]] +} 2> /dev/null || { set +x; err_exit "foo<bar with -x enabled" ;} +set +x +( + eval "[[ (a) ]]" +) 2> /dev/null || err_exit "[[ (a) ]] not working" +> $file +chmod 4755 "$file" +if test -u $file && test ! -u $file +then err_exit "test ! -u suidfile not working" +fi +for i in '(' ')' '[' ']' +do [[ $i == $i ]] || err_exit "[[ $i != $i ]]" +done +( + [[ aaaa == {4}(a) ]] || err_exit 'aaaa != {4}(a)' + [[ aaaa == {2,5}(a) ]] || err_exit 'aaaa != {2,4}(a)' + [[ abcdcdabcd == {3,6}(ab|cd) ]] || err_exit 'abcdcdabcd == {3,4}(ab|cd)' + [[ abcdcdabcde == {5}(ab|cd)e ]] || err_exit 'abcdcdabcd == {5}(ab|cd)e' +) || err_exit 'Errors with {..}(...) patterns' +[[ D290.2003.02.16.temp == D290.+(2003.02.16).temp* ]] || err_exit 'pattern match bug with +(...)' +rm -rf $file +{ +[[ -N $file ]] && err_exit 'test -N /tmp/*: st_mtime>st_atime after creat' +sleep 2 +print 'hello world' +[[ -N $file ]] || err_exit 'test -N /tmp/*: st_mtime<=st_atime after write' +sleep 2 +read +[[ -N $file ]] && err_exit 'test -N /tmp/*: st_mtime>st_atime after read' +} > $file < $file +if rm -rf "$file" && ln -s / "$file" +then [[ -L "$file" ]] || err_exit '-L not working' + [[ -L "$file"/ ]] && err_exit '-L with file/ not working' +fi +$SHELL -c 't=1234567890; [[ $t == @({10}(\d)) ]]' 2> /dev/null || err_exit ' @({10}(\d)) pattern not working' +$SHELL -c '[[ att_ == ~(E)(att|cus)_.* ]]' 2> /dev/null || err_exit ' ~(E)(att|cus)_* pattern not working' +$SHELL -c '[[ att_ =~ (att|cus)_.* ]]' 2> /dev/null || err_exit ' =~ ere not working' +$SHELL -c '[[ abc =~ a(b)c ]]' 2> /dev/null || err_exit '[[ abc =~ a(b)c ]] fails' +$SHELL -xc '[[ abc =~ \babc\b ]]' 2> /dev/null || err_exit '[[ abc =~ \babc\b ]] fails' +[[ abc == ~(E)\babc\b ]] || err_exit '\b not preserved for ere when not in ()' +[[ abc == ~(iEi)\babc\b ]] || err_exit '\b not preserved for ~(iEi) when not in ()' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/builtins.sh b/usr/src/lib/libshell/common/tests/builtins.sh new file mode 100644 index 0000000000..1d2dfe9157 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/builtins.sh @@ -0,0 +1,451 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +# test shell builtin commands +Command=${0##*/} +integer Errors=0 +builtin getconf +: ${foo=bar} || err_exit ": failed" +[[ $foo = bar ]] || err_exit ": side effects failed" +set -- - foobar +[[ $# = 2 && $1 = - && $2 = foobar ]] || err_exit "set -- - foobar failed" +set -- -x foobar +[[ $# = 2 && $1 = -x && $2 = foobar ]] || err_exit "set -- -x foobar failed" +getopts :x: foo || err_exit "getopts :x: returns false" +[[ $foo = x && $OPTARG = foobar ]] || err_exit "getopts :x: failed" +OPTIND=1 +getopts :r:s var -r +if [[ $var != : || $OPTARG != r ]] +then err_exit "'getopts :r:s var -r' not working" +fi +OPTIND=1 +getopts :d#u var -d 100 +if [[ $var != d || $OPTARG != 100 ]] +then err_exit "'getopts :d#u var -d 100' not working var=$var" +fi +OPTIND=1 +while getopts 'ab' option -a -b +do [[ $OPTIND == $((OPTIND)) ]] || err_exit "OPTIND optimization bug" +done + +USAGE=$'[-][S:server?Operate on the specified \asubservice\a:]:[subservice:=pmserver] + { + [p:pmserver] + [r:repserver] + [11:notifyd] + }' +set pmser p rep r notifyd -11 +while (( $# > 1 )) +do OPTIND=1 + getopts "$USAGE" OPT -S $1 + [[ $OPT == S && $OPTARG == $2 ]] || err_exit "OPT=$OPT OPTARG=$OPTARG -- expected OPT=S OPTARG=$2" + shift 2 +done + +false ${foo=bar} && err_exit "false failed" +read <<! +hello world +! +[[ $REPLY = 'hello world' ]] || err_exit "read builtin failed" +print x:y | IFS=: read a b +if [[ $a != x ]] +then err_exit "IFS=: read ... not working" +fi +read <<! +hello \ +world +! +[[ $REPLY = 'hello world' ]] || err_exit "read continuation failed" +read -d x <<! +hello worldxfoobar +! +[[ $REPLY = 'hello world' ]] || err_exit "read builtin failed" +read <<\! +hello \ + world \ + +! +[[ $REPLY == 'hello world' ]] || err_exit "read continuation2 failed" +print "one\ntwo" | { read line + print $line | /bin/cat > /dev/null + read line +} +read <<\! +\ +a\ +\ +\ +b +! +if [[ $REPLY != ab ]] +then err_exit "read multiple continuation failed" +fi +if [[ $line != two ]] +then err_exit "read from pipeline failed" +fi +line=two +read line < /dev/null +if [[ $line != "" ]] +then err_exit "read from /dev/null failed" +fi +if [[ $(print -R -) != - ]] +then err_exit "print -R not working correctly" +fi +if [[ $(print -- -) != - ]] +then err_exit "print -- not working correctly" +fi +print -f "hello%nbar\n" size > /dev/null +if (( size != 5 )) +then err_exit "%n format of printf not working" +fi +print -n -u2 2>&1- +[[ -w /dev/fd/1 ]] || err_exit "2<&1- with built-ins has side effects" +x=$0 +if [[ $(eval 'print $0') != $x ]] +then err_exit '$0 not correct for eval' +fi +unset x +readonly x +set -- $(readonly) +if [[ " $@ " != *" x "* ]] +then err_exit 'unset readonly variables are not displayed' +fi +if [[ $( for i in foo bar + do print $i + continue 10 + done + ) != $'foo\nbar' ]] +then err_exit 'continue breaks out of loop' +fi +(continue bad 2>/dev/null && err_exit 'continue bad should return an error') +(break bad 2>/dev/null && err_exit 'break bad should return an error') +(continue 0 2>/dev/null && err_exit 'continue 0 should return an error') +(break 0 2>/dev/null && err_exit 'break 0 should return an error') +breakfun() { break;} +continuefun() { continue;} +for fun in break continue +do if [[ $( for i in foo + do ${fun}fun + print $i + done + ) != foo ]] + then err_exit "$fun call in ${fun}fun breaks out of for loop" + fi +done +if [[ $(print -f "%b" "\a\n\v\b\r\f\E\03\\oo") != $'\a\n\v\b\r\f\E\03\\oo' ]] +then err_exit 'print -f "%b" not working' +fi +if [[ $(print -f "%P" "[^x].*b$") != '*[!x]*b' ]] +then err_exit 'print -f "%P" not working' +fi +if [[ $(abc: for i in foo bar;do print $i;break abc;done) != foo ]] +then err_exit 'break labels not working' +fi +if [[ $(command -v if) != if ]] +then err_exit 'command -v not working' +fi +read -r var <<\! + +! +if [[ $var != "" ]] +then err_exit "read -r of blank line not working" +fi +mkdir -p /tmp/ksh$$/a/b/c 2>/dev/null || err_exit "mkdir -p failed" +$SHELL -c "cd /tmp/ksh$$/a/b; cd c" 2>/dev/null || err_exit "initial script relative cd fails" +rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed" +trap 'print HUP' HUP +if [[ $(trap) != "trap -- 'print HUP' HUP" ]] +then err_exit '$(trap) not working' +fi +if [[ $(trap -p HUP) != 'print HUP' ]] +then err_exit '$(trap -p HUP) not working' +fi +[[ $($SHELL -c 'trap "print ok" SIGTERM; kill -s SIGTERM $$' 2> /dev/null) == ok + ]] || err_exit 'SIGTERM not recognized' +[[ $($SHELL -c 'trap "print ok" sigterm; kill -s sigterm $$' 2> /dev/null) == ok + ]] || err_exit 'SIGTERM not recognized' +${SHELL} -c 'kill -1 -$$' 2> /dev/null +[[ $(kill -l $?) == HUP ]] || err_exit 'kill -1 -pid not working' +${SHELL} -c 'kill -1 -$$' 2> /dev/null +[[ $(kill -l $?) == HUP ]] || err_exit 'kill -n1 -pid not working' +${SHELL} -c 'kill -s HUP -$$' 2> /dev/null +[[ $(kill -l $?) == HUP ]] || err_exit 'kill -HUP -pid not working' +n=123 +typeset -A base +base[o]=8# +base[x]=16# +base[X]=16# +for i in d i o u x X +do if (( $(( ${base[$i]}$(printf "%$i" $n) )) != n )) + then err_exit "printf %$i not working" + fi +done +if [[ $( trap 'print done' EXIT) != done ]] +then err_exit 'trap on EXIT not working' +fi +if [[ $( trap 'print done' EXIT; trap - EXIT) == done ]] +then err_exit 'trap on EXIT not being cleared' +fi +if [[ $(type test) != 'test is a shell builtin' ]] +then err_exit 'whence -v test not a builtin' +fi +builtin -d test +if [[ $(type test) == *builtin* ]] +then err_exit 'whence -v test after builtin -d incorrect' +fi +typeset -Z3 percent=$(printf '%o\n' "'%'") +forrmat=\\${percent}s +if [[ $(printf "$forrmat") != %s ]] +then err_exit "printf $forrmat not working" +fi +if (( $(printf 'x\0y' | wc -c) != 3 )) +then err_exit 'printf \0 not working' +fi +if [[ $(printf "%bx%s\n" 'f\to\cbar') != $'f\to' ]] +then err_exit 'printf %bx%s\n not working' +fi +alpha=abcdefghijklmnop +if [[ $(printf "%10.*s\n" 5 $alpha) != ' abcde' ]] +then err_exit 'printf %10.%s\n not working' +fi +float x2=.0000625 +if [[ $(printf "%10.5E\n" x2) != 6.25000E-05 ]] +then err_exit 'printf "%10.5E" not normalizing correctly' +fi +x2=.000000001 +if [[ $(printf "%g\n" x2 2>/dev/null) != 1e-09 ]] +then err_exit 'printf "%g" not working correctly' +fi +#FIXME#($SHELL read -s foobar <<\! +#FIXME#testing +#FIXME#! +#FIXME#) 2> /dev/null || err_exit ksh read -s var fails +if [[ $(printf +3 2>/dev/null) != +3 ]] +then err_exit 'printf is not processing formats beginning with + correctly' +fi +if printf "%d %d\n" 123bad 78 >/dev/null 2>/dev/null +then err_exit "printf not exiting non-zero with conversion errors" +fi +if [[ $(trap --version 2> /dev/null;print done) != done ]] +then err_exit 'trap builtin terminating after --version' +fi +if [[ $(set --version 2> /dev/null;print done) != done ]] +then err_exit 'set builtin terminating after --veresion' +fi +unset -f foobar +function foobar +{ + print 'hello world' +} +OPTIND=1 +if [[ $(getopts $'[+?X\ffoobar\fX]' v --man 2>&1) != *'Xhello world'X* ]] +then err_exit '\f...\f not working in getopts usage strings' +fi +if [[ $(printf '%H\n' $'<>"& \'\tabc') != '<>"& '	abc' ]] +then err_exit 'printf %H not working' +fi +if [[ $(printf '%R %R %R %R\n' 'a.b' '*.c' '^' '!(*.*)') != '^a\.b$ \.c$ ^\^$ ^(.*\..*)!$' ]] +then err_exit 'printf %R not working' +fi +if [[ $(printf '%..:c\n' abc) != a:b:c ]] +then err_exit "printf '%..:c' not working" +fi +if [[ $(printf '%..*c\n' : abc) != a:b:c ]] +then err_exit "printf '%..*c' not working" +fi +if [[ $(printf '%..:s\n' abc def ) != abc:def ]] +then err_exit "printf '%..:s' not working" +fi +if [[ $(printf '%..*s\n' : abc def) != abc:def ]] +then err_exit "printf '%..*s' not working" +fi +[[ $(printf '%q\n') == '' ]] || err_exit 'printf "%q" with missing arguments' +# we won't get hit by the one second boundary twice, right? +[[ $(printf '%T\n' now) == "$(date)" ]] || +[[ $(printf '%T\n' now) == "$(date)" ]] || +err_exit 'printf "%T" now' +behead() +{ + read line + left=$(cat) +} +print $'line1\nline2' | behead +if [[ $left != line2 ]] +then err_exit "read reading ahead on a pipe" +fi +read -n1 y <<! +abc +! +if [[ $y != a ]] +then err_exit 'read -n1 not working' +fi +print -n $'{ read -r line;print $line;}\nhello' > /tmp/ksh$$ +chmod 755 /tmp/ksh$$ +trap 'rm -rf /tmp/ksh$$' EXIT +if [[ $($SHELL < /tmp/ksh$$) != hello ]] +then err_exit 'read of incomplete line not working correctly' +fi +set -f +set -- * +if [[ $1 != '*' ]] +then err_exit 'set -f not working' +fi +unset pid1 pid2 +false & +pid1=$! +pid2=$( + wait $pid1 + (( $? == 127 )) || err_exit "job known to subshell" + print $! +) +wait $pid1 +(( $? == 1 )) || err_exit "wait not saving exit value" +wait $pid2 +(( $? == 127 )) || err_exit "subshell job known to parent" +set --noglob +ifs=$IFS +IFS=, +set -- $(getconf LIBPATH) +IFS=$ifs +env= +for v +do IFS=: + set -- $v + IFS=$ifs + eval [[ \$$2 ]] && env="$env $2=\"\$$2\"" +done +set --glob +if [[ $(foo=bar; eval foo=\$foo $env exec -c \$SHELL -c \'print \$foo\') != bar ]] +then err_exit '"name=value exec -c ..." not working' +fi +$SHELL -c 'OPTIND=-1000000; getopts a opt -a' 2> /dev/null +[[ $? == 1 ]] || err_exit 'getopts with negative OPTIND not working' +getopts 'n#num' opt -n 3 +[[ $OPTARG == 3 ]] || err_exit 'getopts with numerical arguments failed' +if [[ $($SHELL -c $'printf \'%2$s %1$s\n\' world hello') != 'hello world' ]] +then err_exit 'printf %2$s %1$s not working' +fi +((n=0)) +((n++)); ARGC[$n]=1 ARGV[$n]="" +((n++)); ARGC[$n]=2 ARGV[$n]="-a" +((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2" +((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x" +((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x y" +for ((i=1; i<=n; i++)) +do set -- ${ARGV[$i]} + OPTIND=0 + while getopts -a tst "av:" OPT + do : + done + if [[ $OPTIND != ${ARGC[$i]} ]] + then err_exit "\$OPTIND after getopts loop incorrect -- got $OPTIND, expected ${ARGC[$i]}" + fi +done +unset a +{ read -N3 a; read -N1 b;} <<! +abcdefg +! +[[ $a == abc ]] || err_exit 'read -N3 here-document not working' +[[ $b == d ]] || err_exit 'read -N1 here-document not working' +read -n3 a <<! +abcdefg +! +[[ $a == abc ]] || err_exit 'read -n3 here-document not working' +(print -n a;sleep 1; print -n bcde) | { read -N3 a; read -N1 b;} +[[ $a == abc ]] || err_exit 'read -N3 from pipe not working' +[[ $b == d ]] || err_exit 'read -N1 from pipe not working' +(print -n a;sleep 1; print -n bcde) |read -n3 a +[[ $a == a ]] || err_exit 'read -n3 from pipe not working' +rm -f /tmp/fifo$$ +if mkfifo /tmp/fifo$$ 2> /dev/null +then (print -n a; sleep 1;print -n bcde) > /tmp/fifo$$ & + { + read -u5 -n3 -t2 a || err_exit 'read -n3 from fifo timedout' + read -u5 -n1 -t2 b || err_exit 'read -n1 from fifo timedout' + } 5< /tmp/fifo$$ + [[ $a == a ]] || err_exit 'read -n3 from fifo not working' + rm -f /tmp/fifo$$ + mkfifo /tmp/fifo$$ 2> /dev/null + (print -n a; sleep 1;print -n bcde) > /tmp/fifo$$ & + { + read -u5 -N3 -t2 a || err_exit 'read -N3 from fifo timed out' + read -u5 -N1 -t2 b || err_exit 'read -N1 from fifo timedout' + } 5< /tmp/fifo$$ + [[ $a == abc ]] || err_exit 'read -N3 from fifo not working' + [[ $b == d ]] || err_exit 'read -N1 from fifo not working' +fi +rm -f /tmp/fifo$$ +function longline +{ + integer i + for((i=0; i < $1; i++)) + do print argument$i + done +} +# test command -x option +integer sum=0 n=10000 +if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1 +then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) 2> /dev/null) + do ((sum += $i)) + done + (( sum == n )) || err_exit "command -x processed only $sum arguments" + command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1 + [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x' +fi +# test command -x option with extra arguments +integer sum=0 n=10000 +if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1 +then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) one two three) #2> /dev/null) + do ((sum += $i)) + done + (( sum > n )) || err_exit "command -x processed only $sum arguments" + (( (sum-n)%3==0 )) || err_exit "command -x processed only $sum arguments" + (( sum == n+3)) && err_exit "command -x processed only $sum arguments" + command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1 + [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x' +fi +# test for debug trap +[[ $(typeset -i i=0 + trap 'print $i' DEBUG + while (( i <2)) + do (( i++)) + done) == $'0\n0\n1\n1\n2' ]] || err_exit "DEBUG trap not working" +getconf UNIVERSE - ucb +[[ $($SHELL -c 'echo -3') == -3 ]] || err_exit "echo -3 not working in ucb universe" +typeset -F3 start_x=SECONDS total_t delay=0.02 +typeset reps=50 leeway=5 +sleep $(( 2 * leeway * reps * delay )) | +for (( i=0 ; i < reps ; i++ )) +do read -N1 -t $delay +done +(( total_t = SECONDS - start_x )) +if (( total_t > leeway * reps * delay )) +then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too long" +elif (( total_t < reps * delay )) +then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too fast" +fi +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/case.sh b/usr/src/lib/libshell/common/tests/case.sh new file mode 100644 index 0000000000..4090d30103 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/case.sh @@ -0,0 +1,81 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 + +bar=foo2 +bam=foo[3] +for i in foo1 foo2 foo3 foo4 foo5 foo6 +do foo=0 + case $i in + foo1) foo=1;; + $bar) foo=2;; + $bam) foo=3;; + foo[4]) foo=4;; + ${bar%?}5) + foo=5;; + "${bar%?}6") + foo=6;; + esac + if [[ $i != foo$foo ]] + then err_exit "$i not matching correct pattern" + fi +done +f="[ksh92]" +case $f in +\[*\]) ;; +*) err_exit "$f does not match \[*\]";; +esac + +if [[ $($SHELL -c ' + x=$(case abc { + abc) { print yes;};; + *) print no;; + } + ) + print -r -- "$x"' 2> /dev/null) != yes ]] +then err_exit 'case abc {...} not working' +fi +[[ $($SHELL -c 'case a in +a) print -n a > /dev/null ;& +b) print b;; +esac') != b ]] && err_exit 'bug in ;& at end of script' +[[ $(VMDEBUG=1 $SHELL -c ' + tmp=foo + for i in a b + do case $i in + a) : tmp=$tmp tmp.h=$tmp.h;; + b) ( tmp=bar ) + for j in a + do print -r -- $tmp.h + done + ;; + esac + done +') == foo.h ]] || err_exit "optimizer bug" +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/comvar.sh b/usr/src/lib/libshell/common/tests/comvar.sh new file mode 100644 index 0000000000..5dc5c59a1c --- /dev/null +++ b/usr/src/lib/libshell/common/tests/comvar.sh @@ -0,0 +1,197 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +#test for compound variables +Command=${0##*/} +integer Errors=0 +Point=( + float x=1. y=0. +) +eval p="$Point" +if (( (p.x*p.x + p.y*p.y) > 1.01 )) +then err_exit 'compound variable not working' +fi +nameref foo=p +if [[ ${foo.x} != ${Point.x} ]] +then err_exit 'reference to compound object not working' +fi +unset foo +rec=( + name='Joe Blow' + born=( + month=jan + integer day=16 + year=1980 + ) +) +eval newrec="$rec" +if [[ ${newrec.name} != "${rec.name}" ]] +then err_exit 'copying a compound object not working' +fi +if (( newrec.born.day != 16 )) +then err_exit 'copying integer field of compound object not working' +fi +p_t=( + integer z=0 + typeset -A tokens +) +unset x +typeset -A x +x=( [foo]=bar ) +if [[ ${x[@]} != bar ]] +then err_exit 'compound assignemnt of associative arrays not working' +fi +unset -n foo x +unset foo x +foo=( x=3) +nameref x=foo +if [[ ${!x.@} != foo.x ]] +then err_exit 'name references not expanded on prefix matching' +fi +unset x +( + x=() + x.foo.bar=7 + [[ ${x.foo.bar} == 7 ]] || err_exit '[[ ${x.foo.bar} != 7 ]]' + (( x.foo.bar == 7 ))|| err_exit '(( x.foo.bar != 7 ))' + [[ ${x.foo} == *bar=7* ]] || err_exit '[[ ${x.foo} != *bar=7* ]]' +) +foo=(integer x=3) +if [[ ${foo} != *x=3* ]] +then err_exit "compound variable with integer subvariable not working" +fi +$SHELL -c $'x=(foo=bar)\n[[ x == x ]]' 2> /dev/null || + err_exit '[[ ... ]] not working after compound assignment' +unset foo +[[ ${!foo.@} ]] && err_exit 'unset compound variable leaves subvariables' +suitable=( + label="Table Viewer" + langs="ksh" + uselang=ksh + launch=no + groups="default" + default=( + label="Table Viewer Preferences" + entrylist=" \ + vieworigin viewsize viewcolor viewfontname viewfontsize \ + showheader header showfooter footer showtitle title showlegends \ + class_td_lg1_style class_tr_tr1_style \ + class_th_th1_style class_td_td1_style \ + fields fieldorder \ + " + entries=( + vieworigin=( + type=coord var=vieworigin val="0 0" label="Window Position" + ) + viewsize=( + type=coord var=viewsize val="400 400" label="Window Size" + ) + viewcolor=( + type=2colors var=viewcolor val="gray black" + label="Window Colors" + ) + viewfontname=( + type=fontname var=viewfontname val="Times-Roman" + label="Window Font Name" + ) + viewfontsize=( + type=fontsize var=viewfontsize val=14 label="Window Font Size" + ) + + showheader=( + type=yesno var=showheader val=no label="Show Header" + ) + header=( + type=text var=header val="" label="Header" + ) + + showfooter=( + type=yesno var=showfooter val=no label="Show Footer" + ) + footer=( + type=text var=footer val="" label="Footer" + ) + + showtitle=( + type=yesno var=showtitle val=yes label="Show Title" + ) + title=( + type=text var=title val="SWIFTUI - Table View" label="Title" + ) + + showlegends=( + type=yesno var=showlegends val=yes label="Show Legends" + ) + + class_td_lg1_style=( + type=style var=class_td_lg1_style + val="color: black; font-family: Times-Roman; font-size: 14pt" + label="Legend 1 Style" + ) + + class_tr_tr1_style=( + type=style var=class_tr_tr1_style val="background: black" + label="Table Row 1 Style" + ) + + class_th_th1_style=( + type=style var=class_th_th1_style + val="color: black; font-family: Times-Roman; font-size: 14pt; text-align: left" + label="Table Header 1 Style" + ) + + class_td_td1_style=( + type=style var=class_td_td1_style + val="color: black; font-family: Times-Roman; font-size: 14pt; text-align: left" + label="Table Cell 1 Style" + ) + + fields=( + type=text var=fields val= label="List of Fields" + ) + fieldorder=( + type=text var=fieldorder val= label="Order of Fields" + ) + ) + ) +) +[[ "${suitable}" == *entrylist=* ]] || err_exit 'compound variable expansion omitting fields' +foo=( bar=foo barbar=bar) +[[ $foo == *bar=foo* ]] || err_exit 'no prefix elements in compound variable output' +function localvar +{ + typeset point=(typeset -i x=3 y=4) + (( (point.x*point.x + point.y*point.y) == 25 )) || err_exit "local compound variable not working" +} +point=(integer x=6 y=8) +localvar + (( (point.x*point.x + point.y*point.y) == 100 )) || err_exit "global compound variable not preserved" +[[ $($SHELL -c 'foo=();foo.[x]=(y z); print ${foo.x[@]}') == 'y z' ]] 2> /dev/null || err_exit 'foo=( [x]=(y z) not working' +unset z +( [[ ${z.foo.bar:-abc} == abc ]] 2> /dev/null) || err_exit ':- not working with compound variables' +exit $((Errors)) + diff --git a/usr/src/lib/libshell/common/tests/coprocess.sh b/usr/src/lib/libshell/common/tests/coprocess.sh new file mode 100644 index 0000000000..5bbbdf759a --- /dev/null +++ b/usr/src/lib/libshell/common/tests/coprocess.sh @@ -0,0 +1,218 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +# test the behavior of co-processes +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 + +if [[ -d /cygdrive ]] +then err_exit cygwin detected - coprocess tests disabled - enable at the risk of wedging your system + exit $((Errors)) +fi + +function ping # id +{ + integer x=0 + while ((x < 5)) + do read -r + print -r "$1 $REPLY" + done +} + +cat |& +print -p "hello" +read -p line +[[ $line == hello ]] || err_exit 'coprocessing fails' +exec 5>&p 6<&p +print -u5 'hello again' || err_exit 'write on u5 fails' +read -u6 line +[[ $line == 'hello again' ]] || err_exit 'coprocess after moving fds fails' +exec 5<&- 6<&- + +ping three |& +exec 3>&p +ping four |& +exec 4>&p +ping pipe |& + +integer count +for i in three four pipe four pipe four three pipe pipe three pipe +do case $i in + three) to=-u3;; + four) to=-u4;; + pipe) to=-p;; + esac + count=count+1 + print $to $i $count +done + +while ((count > 0)) +do count=count-1 + read -p +# print -r - "$REPLY" + set -- $REPLY + if [[ $1 != $2 ]] + then err_exit "$1 does not match 2" + fi + case $1 in + three);; + four) ;; + pipe) ;; + *) err_exit "unknown message +|$REPLY|+" + esac +done + +file=/tmp/regress$$ +trap "rm -f $file" EXIT +cat > $file <<\! +/bin/cat |& +! +chmod +x $file +$file 2> /dev/null || err_exit "parent coprocess prevents script coprocess" +exec 5<&p 6>&p +exec 5<&- 6>&- +${SHELL-ksh} |& +print -p $'print hello | cat\nprint Done' +read -t 5 -p +read -t 5 -p +if [[ $REPLY != Done ]] +then err_exit "${SHELL-ksh} coprocess not working" +fi +exec 5<&p 6>&p +exec 5<&- 6>&- +count=0 +{ +echo line1 | grep 'line2' +echo line2 | grep 'line1' +} |& +SECONDS=0 +while + read -p -t 10 line +do + ((count = count + 1)) + echo "Line $count: $line" +done +if (( SECONDS > 8 )) +then err_exit 'read -p hanging' +fi +( sleep 3 |& sleep 1 && kill $!; sleep 1; sleep 3 |& sleep 1 && kill $! ) || + err_exit "coprocess cleanup not working correctly" +unset line +( + integer n=0 + while read line + do echo $line |& + if cat <&p + then ((n++)) + wait $! + fi + done > /dev/null 2>&1 <<- ! + line1 + line2 + line3 + line4 + line5 + line6 + line7 + ! + (( n==7 )) && print ok +) | read -t 10 line +if [[ $line != ok ]] +then err_exit 'coprocess timing bug' +fi +( + /bin/cat |& + exec 6>&p + print -u6 ok + exec 6>&- + sleep 1 + kill $! 2> /dev/null +) && err_exit 'coprocess with subshell would hang' +for sig in IOT ABRT +do if ( trap - $sig ) 2> /dev/null + then if [[ $( + cat |& + pid=$! + trap "print TRAP" $sig + ( + sleep 2 + kill -$sig $$ + sleep 2 + kill -$sig $$ + kill $pid + ) 2> /dev/null & + read -p + ) != $'TRAP\nTRAP' ]] + then err_exit 'traps when reading from coprocess not working' + fi + break + fi +done + +trap 'sleep_pid=; kill $pid; err_exit "coprocess 1 hung"' TERM +{ sleep 5; kill $$; } & +sleep_pid=$! +builtin cat +cat |& +pid=$! +exec 5<&p 6>&p +print -u6 hi; read -u5 +[[ $REPLY == hi ]] || err_exit 'REPLY is $REPLY not hi' +exec 6>&- +wait $pid +trap - TERM +[[ $sleep_pid ]] && kill $sleep_pid + +trap 'sleep_pid=; kill $pid; err_exit "coprocess 2 hung"' TERM +{ sleep 5; kill $$; } & +sleep_pid=$! +cat |& +pid=$! +print foo >&p 2> /dev/null || err_exit 'first write of foo to coprocess failed' +print foo >&p 2> /dev/null || err_exit 'second write of foo to coprocess failed' +kill $pid +wait $pid 2> /dev/null +trap - TERM +[[ $sleep_pid ]] && kill $sleep_pid + +trap 'sleep_pid=; kill $pid; err_exit "coprocess 3 hung"' TERM +{ sleep 5; kill $$; } & +sleep_pid=$! +cat |& +pid=$! +print -p foo +print -p bar +read <&p || err_exit 'first read from coprocess failed' +[[ $REPLY == foo ]] || err_exit "first REPLY is $REPLY not foo" +read <&p || err_exit 'second read from coprocess failed' +[[ $REPLY == bar ]] || err_exit "second REPLY is $REPLY not bar" +kill $pid +wait $pid 2> /dev/null +trap - TERM +[[ $sleep_pid ]] && kill $sleep_pid + +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/exit.sh b/usr/src/lib/libshell/common/tests/exit.sh new file mode 100644 index 0000000000..b099ccfecc --- /dev/null +++ b/usr/src/lib/libshell/common/tests/exit.sh @@ -0,0 +1,81 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +function abspath +{ + base=$(basename $SHELL) + cd ${SHELL%/$base} + newdir=$(pwd) + cd ~- + print $newdir/$base +} +#test for proper exit of shell +Command=${0##*/} +integer Errors=0 +builtin getconf +ABSHELL=$(abspath) +mkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed" +cd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed" +print exit 0 >.profile +${ABSHELL} <<! +HOME=$PWD \ +PATH=$PATH \ +SHELL=$ABSSHELL \ +$( + set --noglob + ifs=$IFS + IFS=, + set -- $(getconf LIBPATH) + IFS=$ifs + for v + do IFS=: + set -- $v + IFS=$ifs + eval [[ \$$2 ]] && eval print -n \" \"\$2=\"\$$2\" + done +) \ +exec -c -a -ksh ${ABSHELL} -c "exit 1" 1>/dev/null 2>&1 +! +status=$(echo $?) +if [[ -o noprivileged && $status != 0 ]] +then err_exit 'exit in .profile is ignored' +elif [[ -o privileged && $status == 0 ]] +then err_exit 'privileged .profile not ignored' +fi +if [[ $(trap 'code=$?; echo $code; trap 0; exit $code' 0; exit 123) != 123 ]] +then err_exit 'exit not setting $?' +fi +cat > run.sh <<- "EOF" + trap 'code=$?; echo $code; trap 0; exit $code' 0 + ( trap 0; exit 123 ) +EOF +if [[ $($SHELL ./run.sh) != 123 ]] +then err_exit 'subshell trap on exit overwrites parent trap' +fi +cd ~- || err_exit "cd back failed" +rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed" +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/expand.sh b/usr/src/lib/libshell/common/tests/expand.sh new file mode 100644 index 0000000000..70018b1feb --- /dev/null +++ b/usr/src/lib/libshell/common/tests/expand.sh @@ -0,0 +1,123 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$Line]: "$@" + ((Errors++)) +} + +integer Errors=0 +Command=${0##*/} + +# {...} expansion tests -- ignore if not supported + +[[ $(print a{0,1}z) == "a0z a1z" ]] || exit 0 + +integer Line=$LINENO+1 +set -- \ + 'ff{c,b,a}' 'ffc ffb ffa' \ + 'f{d,e,f}g' 'fdg feg ffg' \ + '{l,n,m}xyz' 'lxyz nxyz mxyz' \ + '{abc\,def}' '{abc,def}' \ + '{abc}' '{abc}' \ + '\{a,b,c,d,e}' '{a,b,c,d,e}' \ + '{x,y,\{a,b,c}}' 'x} y} {a} b} c}' \ + '{x\,y,\{abc\},trie}' 'x,y {abc} trie' \ + '/usr/{ucb/{ex,edit},lib/{ex,how_ex}}' '/usr/ucb/ex /usr/ucb/edit /usr/lib/ex /usr/lib/how_ex' \ + 'XXXX\{a,b,c\}' 'XXXX{a,b,c}' \ + '{}' '{}' \ + '{ }' '{ }' \ + '}' '}' \ + '{' '{' \ + 'abcd{efgh' 'abcd{efgh' \ + 'foo {1,2} bar' 'foo 1 2 bar' \ + '`print -r -- foo {1,2} bar`' 'foo 1 2 bar' \ + '$(print -r -- foo {1,2} bar)' 'foo 1 2 bar' \ + '{1..10}' '1 2 3 4 5 6 7 8 9 10' \ + '{0..10,braces}' '0..10 braces' \ + '{{0..10},braces}' '0 1 2 3 4 5 6 7 8 9 10 braces' \ + 'x{{0..10},braces}y' 'x0y x1y x2y x3y x4y x5y x6y x7y x8y x9y x10y xbracesy' \ + '{3..3}' '3' \ + 'x{3..3}y' 'x3y' \ + '{10..1}' '10 9 8 7 6 5 4 3 2 1' \ + '{10..1}y' '10y 9y 8y 7y 6y 5y 4y 3y 2y 1y' \ + 'x{10..1}y' 'x10y x9y x8y x7y x6y x5y x4y x3y x2y x1y' \ + '{a..f}' 'a b c d e f' \ + '{f..a}' 'f e d c b a' \ + '{a..A}' '{a..A}' \ + '{A..a}' '{A..a}' \ + '{f..f}' 'f' \ + '{1..f}' '{1..f}' \ + '{f..1}' '{f..1}' \ + '0{1..9} {10..20}' '01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20' \ + '{-1..-10}' '-1 -2 -3 -4 -5 -6 -7 -8 -9 -10' \ + '{-19..0}' '-19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0' \ + '{0..10}' '0 1 2 3 4 5 6 7 8 9 10' \ + '{0..10..1}' '0 1 2 3 4 5 6 7 8 9 10' \ + '{0..10..2}' '0 2 4 6 8 10' \ + '{0..10..3}' '0 3 6 9' \ + '{0..10..0}' '{0..10..0}' \ + '{0..10..-1}' '0' \ + '{10..0}' '10 9 8 7 6 5 4 3 2 1 0' \ + '{10..0..-1}' '10 9 8 7 6 5 4 3 2 1 0' \ + '{10..0..-2}' '10 8 6 4 2 0' \ + '{10..0..-3}' '10 7 4 1' \ + '{10..0..0}' '{10..0..0}' \ + '{10..0..1}' '10' \ + '{a..z..2}' 'a c e g i k m o q s u w y' \ + '{y..b..-3}' 'y v s p m j g d' \ + '{0..0x1000..0x200}' '0 512 1024 1536 2048 2560 3072 3584 4096' \ + '{a,b}{0..2}{z,y}' 'a0z a0y a1z a1y a2z a2y b0z b0y b1z b1y b2z b2y' \ + '{0..0100..8%03o}' '000 010 020 030 040 050 060 070 100' \ + '{0..0100..040%020o}' '00000000000000000000 00000000000000000040 00000000000000000100' \ + '{0..7%03..2u}' '000 001 010 011 100 101 110 111' \ + '{0..10%llu}' '{0..10%llu}' \ + '{0..10%s}' '{0..10%s}' \ + '{0..10%dl}' '{0..10%dl}' \ + '{a,b}{0..3%02..2u}{y,z}' 'a00y a00z a01y a01z a10y a10z a11y a11z b00y b00z b01y b01z b10y b10z b11y b11z' \ + +while (($#>1)) +do ((Line++)) + pattern=$1 + shift + expected=$1 + shift + got=$(eval print -r -- "$pattern") + [[ $got == $expected ]] || err_exit "'$pattern' failed -- expected '$expected' got '$got'" + #print -r -- " '$pattern' '$got' \\" +done + +# ~(N) no expand glob pattern option +set -- ~(N)/dev/null +[[ $# == 1 && $1 == /dev/null ]] || err_exit "~(N)/dev/null not matching /dev/null" +set -- ~(N)/dev/non_existant_file +[[ $# == 0 ]] || err_exit "~(N)/dev/nonexistant not empty" +set -- ""~(N)/dev/non_existant_file +[[ $# == 1 && ! $1 ]] || err_exit '""~(N)/dev/nonexistant not null argument' +set -- ~(N)/dev/non_existant_file"" +[[ $# == 1 && ! $1 ]] || err_exit '~(N)/dev/nonexistent"" not null argument' +for i in ~(N)/dev/non_existent_file +do err_exit "~(N)/dev/non_existent_file in for loop is $i" +done +for i in ""~(N)/dev/non_existent_file +do [[ ! $i ]] || err_exit '""~(N)/dev/non_existent_file not null' +done +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/functions.sh b/usr/src/lib/libshell/common/tests/functions.sh new file mode 100644 index 0000000000..fd45cd1767 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/functions.sh @@ -0,0 +1,758 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +integer Errors=0 +Command=${0##*/} +integer foo=33 +bar=bye +# check for global variables and $0 +function foobar +{ + case $1 in + 1) print -r - "$foo" "$bar";; + 2) print -r - "$0";; + 3) typeset foo=foo + integer bar=10 + print -r - "$foo" "$bar";; + 4) trap 'foo=36' EXIT + typeset foo=20;; + esac +} +function print +{ + command print hi +} +if [[ $(print) != hi ]] +then err_exit "command print not working inside print function" +fi +unset -f print + +if [[ $(foobar 1) != '33 bye' ]] +then err_exit 'global variables not correct' +fi + +if [[ $(foobar 2) != 'foobar' ]] +then err_exit '$0 not correct' +fi + +if [[ $(bar=foo foobar 1) != '33 foo' ]] +then err_exit 'environment override not correct' +fi +if [[ $bar == foo ]] +then err_exit 'scoping error' +fi + +if [[ $(foobar 3) != 'foo 10' ]] +then err_exit non-local variables +fi + +foobar 4 +if [[ $foo != 36 ]] +then err_exit EXIT trap in wrong scope +fi +unset -f foobar || err_exit "cannot unset function foobar" +typeset -f foobar>/dev/null && err_exit "typeset -f has incorrect exit status" + +function foobar +{ + (return 0) +} +> /tmp/shtests$$.1 +{ +foobar +if [ -r /tmp/shtests$$.1 ] +then rm -r /tmp/shtests$$.1 +else err_exit 'return within subshell inside function error' +fi +} +abc() print hi +if [[ $(abc) != hi ]] +then err_exit 'abc() print hi not working' +fi +( unset -f abc ) +if [[ $(abc 2>/dev/null) != hi ]] +then err_exit 'abc() print hi not working after subshell unset' +fi +( + function f + { + exit 1 + } + f + err_exit 'exit from function not working' +) +unset -f foo +function foo +{ + x=2 + ( + x=3 + cd /tmp + print bar + ) + if [[ $x != 2 ]] + then err_exit 'value of x not restored after subshell inside function' + fi +} +x=1 +dir=$PWD +if [[ $(foo) != bar ]] +then err_exit 'cd inside nested subshell not working' +fi +if [[ $PWD != "$dir" ]] +then err_exit 'cd inside nested subshell changes $PWD' +fi +fun() /bin/echo hello +if [[ $(fun) != hello ]] +then err_exit one line functions not working +fi +trap 'rm -f /tmp/script$$ /tmp/data$$.[12]' EXIT +cat > /tmp/script$$ <<-\! + print -r -- "$1" +! +chmod +x /tmp/script$$ +function passargs +{ + /tmp/script$$ "$@" +} +if [[ $(passargs one) != one ]] +then err_exit 'passing args from functions to scripts not working' +fi +cat > /tmp/script$$ <<-\! + trap 'exit 0' EXIT + function foo + { + /tmp > /dev/null 2>&1 + } + foo +! +if ! /tmp/script$$ +then err_exit 'exit trap incorrectly triggered' +fi +if ! $SHELL -c /tmp/script$$ +then err_exit 'exit trap incorrectly triggered when invoked with -c' +fi +$SHELL -c "trap 'rm /tmp/script$$' EXIT" +if [[ -f /tmp/script$$ ]] +then err_exit 'exit trap not triggered when invoked with -c' +fi +cat > /tmp/script$$ <<- \EOF + foobar() + { + return + } + shift + foobar + print -r -- "$1" +EOF +chmod +x /tmp/script$$ +if [[ $( $SHELL /tmp/script$$ arg1 arg2) != arg2 ]] +then err_exit 'arguments not restored by posix functions' +fi +function foo +{ + print hello +} +( + function foo + { + print bar + } + if [[ $(foo) != bar ]] + then err_exit 'function definitions inside subshells not working' + fi +) +if [[ $(foo) != hello ]] +then err_exit 'function definitions inside subshells not restored' +fi +unset -f foo bar +function bar +{ + print "$y" +} + +function foo +{ + typeset x=3 + y=$x bar +} +x=1 +if [[ $(foo) != 3 ]] +then err_exit 'variable assignment list not using parent scope' +fi +unset -f foo$$ +trap "rm -f /tmp/foo$$" EXIT INT +cat > /tmp/foo$$ <<! +function foo$$ +{ + print foo +} +! +chmod +x /tmp/foo$$ +FPATH=/tmp +autoload foo$$ +if [[ $(foo$$ 2>/dev/null) != foo ]] +then err_exit 'autoload not working' +fi +unset -f foobar +function foobar +{ + typeset -r x=3 + return 0 +} +( foobar ) 2> /dev/null || err_exit "cannot unset readonly variable in function" +if $SHELL -n 2> /dev/null <<-! + abc() + ! +then err_exit 'abc() without a function body is not a syntax error' +fi +function winpath +{ + usage='q pathname ...' + typeset var format=s + while getopts "$usage" var + do case $var in + q) format=q;; + esac + done + print done +} +if [[ $( (winpath --man 2>/dev/null); print ok) != ok ]] +then err_exit 'getopts --man in functions not working' +fi +if [[ $( (winpath -z 2>/dev/null); print ok) != ok ]] +then err_exit 'getopts with bad option in functions not working' +fi +unset -f x +function x +{ + print "$@" +} +typeset -ft x +if [[ $(x x=y 2>/dev/null) != x=y ]] +then err_exit 'name=value pair args not passed to traced functions' +fi +function bad +{ + false +} +trap 'val=false' ERR +val=true +bad +if [[ $val != false ]] +then err_exit 'set -e not working for functions' +fi +function bad +{ + false + return 0 +} +val=true +bad +if [[ $val != true ]] +then err_exit 'set -e not disabled for functions' +fi +bad() +{ + false + return 0 +} +val=true +bad +if [[ $val != false ]] +then err_exit 'set -e not inherited for posix functions' +fi +function myexport +{ + nameref var=$1 + if (( $# > 1 )) + then export $1=$2 + fi + if (( $# > 2 )) + then print $(myexport "$1" "$3" ) + return + fi + typeset val + val=$(export | grep "^$1=") + print ${val#"$1="} + +} +export dgk=base +if [[ $(myexport dgk fun) != fun ]] +then err_exit 'export inside function not working' +fi +val=$(export | grep "^dgk=") +if [[ ${val#dgk=} != base ]] +then err_exit 'export not restored after function call' +fi +if [[ $(myexport dgk fun fun2) != fun2 ]] +then err_exit 'export inside function not working with recursive function' +fi +val=$(export | grep "^dgk=") +if [[ ${val#dgk=} != base ]] +then err_exit 'export not restored after recursive function call' +fi +if [[ $(dgk=try3 myexport dgk) != try3 ]] +then err_exit 'name=value not added to export list with function call' +fi +val=$(export | grep "^dgk=") +if [[ ${val#dgk=} != base ]] +then err_exit 'export not restored name=value function call' +fi +unset zzz +if [[ $(myexport zzz fun) != fun ]] +then err_exit 'export inside function not working for zzz' +fi +if [[ $(export | grep "zzz=") ]] +then err_exit 'zzz exported after function call' +fi +unset zzz +typeset -u zzz +function foo +{ + zzz=abc + print $zzz +} +if [[ $(foo)$(foo) != ABCABC ]] +then err_exit 'attributes on unset variables not saved/restored' +fi +function xpd { + typeset i j=$1 + for i + do print i=$i j=$j + [[ $i == a ]] && xpd b + done + } +if [[ $(xpd a c) != $'i=a j=a\ni=b j=b\ni=c j=a' ]] +then err_exit 'for loop function optimization error' +fi + +typeset -A visited +integer level=0 +function closure +{ + (( $# > 5 )) && return 1 + ((level < 2)) && ((level++)) + typeset tmp r=0 + visited[$1]=1 + + for tmp in $level _$level + do + [[ ${visited[$tmp]} == 1 ]] && continue + closure $tmp $* || r=1 + done + return $r +} +closure 0 || err_exit -u2 'for loop function optimization bug2' +mkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed" +cd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed" +print 'false' > try +chmod +x try +cat > tst <<- EOF + function ignore + { + ./try + return 0 + } + trap "print error; exit 1" ERR + ignore +EOF +if [[ $($SHELL < tst) == error ]] +then err_exit 'ERR trap not cleared' +fi +FPATH=/tmp/ksh$$ +print ': This does nothing' > /tmp/ksh$$/foobar +chmod +x /tmp/ksh$$/foobar +unset -f foobar +{ foobar;} 2> /dev/null +if [[ $? != 126 ]] +then err_exit 'function file without function definition processes wrong error' +fi +print 'set a b c' > dotscript +[[ $(PATH=$PATH: $SHELL -c '. dotscript;print $#') == 3 ]] || err_exit 'positional parameters not preserved with . script without arguments' +cd ~- || err_exit "cd back failed" +cd /; rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed" +function errcheck +{ + trap 'print ERR; return 1' ERR + false + print ok +} +err=$(errcheck) +[[ $err == ERR ]] || err_exit 'trap on ERR not working in a function' +x="$( + function foobar + { + print ok + } + typeset -f foobar +)" +eval "$x" || err_exit 'typeset -f generates syntax error' +[[ $(foobar) != ok ]] && err_exit 'typeset -f not generating function' +unset -f a b c +a() +{ + b + b + print ${.sh.fun} +} +b() { : ;} +[[ $(a) == a ]] || err_exit '.sh.fun not set correctly in a function' +print $'a(){\ndate\n}' | $SHELL 2> /dev/null || err_exit 'parser error in a(){;date;}' +cat > /tmp/data$$.1 << '++EOF' + 1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 4 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 8 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 12 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 13 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 14 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 15 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 16 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 17 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 18 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 19 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + 20 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +++EOF +cat > /tmp/script$$ << '++EOF' +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +f() +{ +cat <<\M +++EOF +cat /tmp/data$$.1 >> /tmp/script$$ +printf 'M\n}\n\nf\n\n' >> /tmp/script$$ +$SHELL -c /tmp/script$$ > /tmp/data$$.2 +cmp -s /tmp/data$$.[12] || err_exit 'error with long functions' +rm -f /tmp/script$$ /tmp/data$$.[12] +v=1 +function f +{ + typeset i + for i in 0 1 + do typeset v + v=$i + [[ $v == $i ]] || return 1 + done +} +f || err_exit "typeset optimization bug" +function f +{ + print -r -- "$foo$bar" +} +function g +{ + print -r -- $(bar=bam f) +} +unset foo bar +[[ $(foo=hello g) == hellobam ]] || err_exit 'function exports not passed on' +[[ $(bar=hello g) == bam ]] || err_exit 'function exports not overridden' +unset -f foo +function foo +{ + typeset line=$1 + set +n + while [[ $line ]] + do if [[ ! $varname ]] + then varname=${line%% *} + line=${line##"$varname"?( )} + [[ $line ]] && continue + else print ok + return + fi + varname= + done +} +[[ $(foo 'NUMBERED RECORDSIZE') == ok ]] || err_exit 'optimization error with undefined variable' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/glob.sh b/usr/src/lib/libshell/common/tests/glob.sh new file mode 100644 index 0000000000..4d5fa0b519 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/glob.sh @@ -0,0 +1,303 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + ((errors++)) +} +alias err_exit='err_exit $LINENO' + +integer aware=0 contrary=0 ignorant=0 + +function test_glob +{ + typeset lineno expected drop arg got sep op val add del + if [[ $1 == --* ]] + then del=${1#--} + shift + fi + if [[ $1 == ++* ]] + then add=${1#++} + shift + fi + lineno=$1 expected=$2 + shift 2 + if (( contrary )) + then if [[ $expected == "<Beware> "* ]] + then expected=${expected#"<Beware> "} + expected="$expected <Beware>" + fi + if [[ $expected == *"<aXb> <abd>"* ]] + then expected=${expected/"<aXb> <abd>"/"<abd> <aXb>"} + fi + fi + for arg + do got="$got$sep<$arg>" + sep=" " + done + if (( ignorant && aware )) + then if [[ $del ]] + then got="<$del> $got" + fi + if [[ $add ]] + then expected="<$add> $expected" + fi + fi + if [[ $got != "$expected" ]] + then err_exit $lineno "glob: got '$got' expected '$expected'" + fi +} + +function test_case +{ + typeset lineno expected subject pattern got + lineno=$1 expected=$2 subject=$3 pattern=$4 + eval " + case $subject in + $pattern) got='<match>' ;; + *) got='<nomatch>' ;; + esac + " + if [[ $got != "$expected" ]] + then err_exit $lineno "case $subject in $pattern) got '$got' expected '$expected'" + fi +} + +Command=${0##*/} +tmp=/tmp/ksh$$ +integer errors=0 +unset undefined + +export LC_COLLATE=C + +mkdir $tmp || err_exit $LINENO "mkdir $tmp failed" +trap "cd /; rm -rf $tmp" EXIT +cd $tmp || err_exit $LINENO "cd $tmp failed" +rm -rf * + +touch B b +set -- * +case $* in +'b B') contrary=1 ;; +b|B) ignorant=1 ;; +esac +set -- $(/bin/sh -c 'echo [a-c]') +case $* in +B) aware=1 ;; +esac +rm -rf * + +touch a b c d abc abd abe bb bcd ca cb dd de Beware +mkdir bdir + +test_glob $LINENO '<a> <abc> <abd> <abe> <X*>' a* X* +test_glob $LINENO '<a> <abc> <abd> <abe>' \a* + +if ( set --nullglob ) 2>/dev/null +then + set --nullglob + + test_glob $LINENO '<a> <abc> <abd> <abe>' a* X* + + set --nonullglob +fi + +if ( set --failglob ) 2>/dev/null +then + set --failglob + mkdir tmp + touch tmp/l1 tmp/l2 tmp/l3 + + test_glob $LINENO '' tmp/l[12] tmp/*4 tmp/*3 + test_glob $LINENO '' tmp/l[12] tmp/*4 tmp/*3 + + rm -r tmp + set --nofailglob +fi + +test_glob $LINENO '<bdir/>' b*/ +test_glob $LINENO '<*>' \* +test_glob $LINENO '<a*>' 'a*' +test_glob $LINENO '<a*>' a\* +test_glob $LINENO '<c> <ca> <cb> <a*> <*q*>' c* a\* *q* +test_glob $LINENO '<**>' "*"* +test_glob $LINENO '<**>' \** +test_glob $LINENO '<\.\./*/>' "\.\./*/" +test_glob $LINENO '<s/\..*//>' 's/\..*//' +test_glob $LINENO '</^root:/{s/^[!:]*:[!:]*:\([!:]*\).*$/\1/>' "/^root:/{s/^[!:]*:[!:]*:\([!:]*\).*"'$'"/\1/" +test_glob $LINENO '<abc> <abd> <abe> <bb> <cb>' [a-c]b* +test_glob ++Beware $LINENO '<abd> <abe> <bb> <bcd> <bdir> <ca> <cb> <dd> <de>' [a-y]*[!c] +test_glob $LINENO '<abd> <abe>' a*[!c] + +touch a-b aXb + +test_glob $LINENO '<a-b> <aXb>' a[X-]b + +touch .x .y + +test_glob --Beware $LINENO '<Beware> <d> <dd> <de>' [!a-c]* + +if mkdir a\*b 2>/dev/null +then + touch a\*b/ooo + + test_glob $LINENO '<a*b/ooo>' a\*b/* + test_glob $LINENO '<a*b/ooo>' a\*?/* + test_case $LINENO '<match>' '!7' '*\!*' + test_case $LINENO '<match>' 'r.*' '*.\*' + test_glob $LINENO '<abc>' a[b]c + test_glob $LINENO '<abc>' a["b"]c + test_glob $LINENO '<abc>' a[\b]c + test_glob $LINENO '<abc>' a?c + test_case $LINENO '<match>' 'abc' 'a"b"c' + test_case $LINENO '<match>' 'abc' 'a*c' + test_case $LINENO '<nomatch>' 'abc' '"a?c"' + test_case $LINENO '<nomatch>' 'abc' 'a\*c' + test_case $LINENO '<nomatch>' 'abc' 'a\[b]c' + test_case $LINENO '<match>' '"$undefined"' '""' + test_case $LINENO '<match>' 'abc' 'a["\b"]c' + + rm -rf mkdir a\*b +fi + +mkdir man +mkdir man/man1 +touch man/man1/sh.1 + +test_glob $LINENO '<man/man1/sh.1>' */man*/sh.* +test_glob $LINENO '<man/man1/sh.1>' $(echo */man*/sh.*) +test_glob $LINENO '<man/man1/sh.1>' "$(echo */man*/sh.*)" + +test_case $LINENO '<match>' 'abc' 'a***c' +test_case $LINENO '<match>' 'abc' 'a*****?c' +test_case $LINENO '<match>' 'abc' '?*****??' +test_case $LINENO '<match>' 'abc' '*****??' +test_case $LINENO '<match>' 'abc' '*****??c' +test_case $LINENO '<match>' 'abc' '?*****?c' +test_case $LINENO '<match>' 'abc' '?***?****c' +test_case $LINENO '<match>' 'abc' '?***?****?' +test_case $LINENO '<match>' 'abc' '?***?****' +test_case $LINENO '<match>' 'abc' '*******c' +test_case $LINENO '<match>' 'abc' '*******?' +test_case $LINENO '<match>' 'abcdecdhjk' 'a*cd**?**??k' +test_case $LINENO '<match>' 'abcdecdhjk' 'a**?**cd**?**??k' +test_case $LINENO '<match>' 'abcdecdhjk' 'a**?**cd**?**??k***' +test_case $LINENO '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k' +test_case $LINENO '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k**' +test_case $LINENO '<match>' 'abcdecdhjk' 'a****c**?**??*****' +test_case $LINENO '<match>' "'-'" '[-abc]' +test_case $LINENO '<match>' "'-'" '[abc-]' +test_case $LINENO '<match>' "'\\'" '\\' +test_case $LINENO '<match>' "'\\'" '[\\]' +test_case $LINENO '<match>' "'\\'" "'\\'" +test_case $LINENO '<match>' "'['" '[[]' +test_case $LINENO '<match>' '[' '[[]' +test_case $LINENO '<match>' "'['" '[' +test_case $LINENO '<match>' '[' '[' +test_case $LINENO '<match>' "'[abc'" "'['*" +test_case $LINENO '<nomatch>' "'[abc'" '[*' +test_case $LINENO '<match>' '[abc' "'['*" +test_case $LINENO '<nomatch>' '[abc' '[*' +test_case $LINENO '<match>' 'abd' "a[b/c]d" +test_case $LINENO '<match>' 'a/d' "a[b/c]d" +test_case $LINENO '<match>' 'acd' "a[b/c]d" +test_case $LINENO '<match>' "']'" '[]]' +test_case $LINENO '<match>' "'-'" '[]-]' +test_case $LINENO '<match>' 'p' '[a-\z]' +test_case $LINENO '<match>' '"/tmp"' '[/\\]*' +test_case $LINENO '<nomatch>' 'abc' '??**********?****?' +test_case $LINENO '<nomatch>' 'abc' '??**********?****c' +test_case $LINENO '<nomatch>' 'abc' '?************c****?****' +test_case $LINENO '<nomatch>' 'abc' '*c*?**' +test_case $LINENO '<nomatch>' 'abc' 'a*****c*?**' +test_case $LINENO '<nomatch>' 'abc' 'a********???*******' +test_case $LINENO '<nomatch>' "'a'" '[]' +test_case $LINENO '<nomatch>' 'a' '[]' +test_case $LINENO '<nomatch>' "'['" '[abc' +test_case $LINENO '<nomatch>' '[' '[abc' + +test_glob ++Beware $LINENO '<b> <bb> <bcd> <bdir>' b* +test_glob $LINENO '<Beware> <b> <bb> <bcd> <bdir>' [bB]* + +if ( set --nocaseglob ) 2>/dev/null +then + set --nocaseglob + + test_glob $LINENO '<Beware> <b> <bb> <bcd> <bdir>' b* + test_glob $LINENO '<Beware> <b> <bb> <bcd> <bdir>' [b]* + test_glob $LINENO '<Beware> <b> <bb> <bcd> <bdir>' [bB]* + + set --nonocaseglob +fi + +if ( set -f ) 2>/dev/null +then + set -f + + test_glob $LINENO '<*>' * + + set +f +fi + +if ( set --noglob ) 2>/dev/null +then + set --noglob + + test_glob $LINENO '<*>' * + + set --glob +fi + +FIGNORE='.*|*' +test_glob $LINENO '<*>' * + +FIGNORE='.*|*c|*e|?' +test_glob $LINENO '<a-b> <aXb> <abd> <bb> <bcd> <bdir> <ca> <cb> <dd> <man>' * + +FIGNORE='.*|*b|*d|?' +test_glob $LINENO '<Beware> <abc> <abe> <bdir> <ca> <de> <man>' * + +FIGNORE= +test_glob $LINENO '<man/man1/sh.1>' */man*/sh.* + +unset FIGNORE +test_glob $LINENO '<bb> <ca> <cb> <dd> <de>' ?? +test_glob $LINENO '<man/man1/sh.1>' */man*/sh.* + +GLOBIGNORE='.*:*' +set -- * +if [[ $1 == '*' ]] +then + GLOBIGNORE='.*:*c:*e:?' + test_glob $LINENO '<>' * + + GLOBIGNORE='.*:*b:*d:?' + test_glob $LINENO '<>' * + + unset GLOBIGNORE + test_glob $LINENO '<>' * + test_glob $LINENO '<man/man1/sh.1>' */man*/sh.* + + GLOBIGNORE= + test_glob $LINENO '<man/man1/sh.1>' */man*/sh.* +fi + +exit $errors diff --git a/usr/src/lib/libshell/common/tests/grep.sh b/usr/src/lib/libshell/common/tests/grep.sh new file mode 100644 index 0000000000..db20206dbf --- /dev/null +++ b/usr/src/lib/libshell/common/tests/grep.sh @@ -0,0 +1,102 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 + +function grep +{ + # + # SHELL VERSION OF GREP + # + vflag= xflag= cflag= lflag= nflag= + set -f + while ((1)) # look for grep options + do case "$1" in + -v*) vflag=1;; + -x*) xflag=1;; + -c*) cflag=1;; + -l*) lflag=1;; + -n*) nflag=1;; + -b*) print 'b option not supported';; + -e*) shift;expr="$1";; + -f*) shift;expr=$(< $1);; + -*) print $0: 'unknown flag';return 2;; + *) + if test "$expr" = '' + then expr="$1";shift + fi + test "$xflag" || expr="*${expr}*" + break;; + esac + shift # next argument + done + noprint=$vflag$cflag$lflag # don't print if these flags are set + integer n=0 c=0 tc=0 nargs=$# # initialize counters + for i in "$@" # go thru the files + do if ((nargs<=1)) + then fname='' + else fname="$i": + fi + test "$i" && exec 0< $i # open file if necessary + while read -r line # read in a line + do let n=n+1 + case "$line" in + $expr) # line matches pattern + test "$noprint" || print -r -- "$fname${nflag:+$n:}$line" + let c=c+1 ;; + *) # not a match + if test "$vflag" + then print -r -- "$fname${nflag:+$n:}$line" + fi;; + esac + done + if test "$lflag" && ((c)) + then print -r -- "$i" + fi + let tc=tc+c n=0 c=0 + done + test "$cflag" && print $tc # print count if cflag is set + let tc # set the return value +} + +trap 'rm -f /tmp/grep$$' EXIT +cat > /tmp/grep$$ <<\! +this is a food bar test +to see how many lines find both foo and bar. +Some line contain foo only, +and some lines contain bar only. +However, many lines contain both foo and also bar. +A line containing foobar should also be counted. +There should be six lines with foo and bar. +There are only two line with out foo but with bar. +! + +if (( $(grep -c 'foo*bar' /tmp/grep$$ ) != 6)) +then err_exit +fi +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/heredoc.sh b/usr/src/lib/libshell/common/tests/heredoc.sh new file mode 100644 index 0000000000..53835f2007 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/heredoc.sh @@ -0,0 +1,213 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +f=/tmp/here1$$ +g=/tmp/here2$$ +trap "rm -f $f $g" EXIT +cat > $f <<! +hello world +! +if [[ $(<$f) != 'hello world' ]] +then err_exit "'hello world' here doc not working" +fi +cat > $g <<\! +hello world +! +cmp $f $g 2> /dev/null || err_exit "'hello world' quoted here doc not working" +cat > $g <<- ! + hello world +! +cmp $f $g 2> /dev/null || err_exit "'hello world' tabbed here doc not working" +cat > $g <<- \! + hello world +! +cmp $f $g 2> /dev/null || err_exit "'hello world' quoted tabbed here doc not working" +x=hello +cat > $g <<! +$x world +! +cmp $f $g 2> /dev/null || err_exit "'$x world' here doc not working" +cat > $g <<! +$(print hello) world +! +cmp $f $g 2> /dev/null || err_exit "'$(print hello) world' here doc not working" +cat > $f <<\!! +!@#$%%^^&*()_+~"::~;'`<>?/.,{}[] +!! +if [[ $(<$f) != '!@#$%%^^&*()_+~"::~;'\''`<>?/.,{}[]' ]] +then err_exit "'hello world' here doc not working" +fi +cat > $g <<!! +!@#\$%%^^&*()_+~"::~;'\`<>?/.,{}[] +!! +cmp $f $g 2> /dev/null || err_exit "unquoted here doc not working" +exec 3<<! + foo +! +if [[ $(<&3) != ' foo' ]] +then err_exit "leading tabs stripped with <<!" +fi +$SHELL -c " +eval `echo 'cat <<x'` "|| err_exit "eval `echo 'cat <<x'` core dumps" +cat > /dev/null <<EOF # comments should not cause core dumps +abc +EOF +cat >$g << : +: +: +cmp /dev/null $g 2> /dev/null || err_exit "empty here doc not working" +x=$(print $( cat <<HUP +hello +HUP +) +) +if [[ $x != hello ]] +then err_exit "here doc inside command sub not working" +fi +y=$(cat <<! +${x:+${x}} +! +) +if [[ $y != "${x:+${x}}" ]] +then err_exit '${x:+${x}} not working in here document' +fi +$SHELL -c ' +x=0 +while (( x < 100 )) +do ((x = x+1)) + cat << EOF +EOF +done +' 2> /dev/null || err_exit '100 empty here docs fails' +{ + print 'builtin -d cat + cat <<- EOF' + for ((i=0; i < 100; i++)) + do print XXXXXXXXXXXXXXXXXXXX + done + print ' XXX$(date)XXXX + EOF' +} > $f +chmod +x "$f" +$SHELL "$f" > /dev/null || err_exit "large here-doc with command substitution fails" +x=$(/bin/cat <<! +$0 +! +) +[[ "$x" == "$0" ]] || err_exit '$0 not correct inside here documents' +$SHELL -c 'x=$( +cat << EOF +EOF)' 2> /dev/null || err_exit 'here-doc cannot be terminated by )' +if [[ $( IFS=:;cat <<-! + $IFS$(print hi)$IFS + !) != :hi: ]] +then err_exit '$IFS unset by command substitution in here docs' +fi +if x=$($SHELL -c 'cat <<< "hello world"' 2> /dev/null) +then [[ $x == 'hello world' ]] || err_exit '<<< documents not working' + x=$($SHELL -c 'v="hello world";cat <<< $v' 2> /dev/null) + [[ $x == 'hello world' ]] || err_exit '<<< documents with $x not working' + x=$($SHELL -c 'v="hello world";cat <<< "$v"' 2> /dev/null) + [[ $x == 'hello world' ]] || err_exit '<<< documents with $x not working' +else err_exit '<<< syntax not supported' +fi +if [[ $(cat << EOF #testing +#abc +abc +EOF) != $'#abc\nabc' ]] +then err_exit 'comments not preserved in here-documents' +fi +cat > "$f" <<- '!!!!' + builtin cat + : << EOF + $PWD + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + EOF + command exec 3>&- 4>&- 5>&- 6>&- 7>&- 8>&- 9>&- + x=abc + cat << EOF + $x + EOF +!!!! +chmod 755 "$f" +if [[ $($SHELL "$f") != abc ]] +then err_exit 'here document descritor was closed' +fi +cat > "$f" <<- '!!!!' + exec 0<&- + foobar() + { + /bin/cat <<- ! + foobar + ! + } + : << EOF + $PWD + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + EOF + print -r -- "$(foobar)" +!!!! +if [[ $($SHELL "$f") != foobar ]] +then err_exit 'here document with stdin closed failed' +fi +printf $'cat <<# \\!!!\n\thello\n\t\tworld\n!!!' > $f +[[ $($SHELL "$f") == $'hello\n\tworld' ]] || err_exit "<<# not working for quoted here documents" +printf $'w=world;cat <<# !!!\n\thello\n\t\t$w\n!!!' > $f +[[ $($SHELL "$f") == $'hello\n\tworld' ]] || err_exit "<<# not working for non-quoted here documents" +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/io.sh b/usr/src/lib/libshell/common/tests/io.sh new file mode 100644 index 0000000000..649520482a --- /dev/null +++ b/usr/src/lib/libshell/common/tests/io.sh @@ -0,0 +1,251 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +# cut here +function fun +{ + while command exec 3>&1 + do break + done 2> /dev/null + print -u3 good +} +print 'read -r a;print -r -u$1 -- "$a"' > /tmp/mycat$$ +chmod 755 /tmp/mycat$$ +for ((i=3; i < 10; i++)) +do + eval "a=\$(print foo | /tmp/mycat$$" $i $i'>&1 > /dev/null |cat)' 2> /dev/null + [[ $a == foo ]] || err_exit "bad file descriptor $i in comsub script" +done +rm -f /tmp/mycat$$ +exec 3> /dev/null +[[ $(fun) == good ]] || err_exit 'file 3 closed before subshell completes' +exec 3>&- +mkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed" +trap 'rm -rf /tmp/ksh$$' EXIT +cd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed" +print foo > file1 +print bar >> file1 +if [[ $(<file1) != $'foo\nbar' ]] +then err_exit 'append (>>) not working' +fi +set -o noclobber +exec 3<> file1 +read -u3 line +if [[ $line != foo ]] +then err_exit '<> not working right with read' +fi +if ( 4> file1 ) 2> /dev/null +then err_exit 'noclobber not causing exclusive open' +fi +set +o noclobber +if command exec 4< /dev/fd/3 +then read -u4 line + if [[ $line != bar ]] + then '4< /dev/fd/3 not working correctly' + fi +fi +cat > close0 <<\! +exec 0<&- +echo $(./close1) +! +print "echo abc" > close1 +chmod +x close0 close1 +x=$(./close0) +if [[ $x != "abc" ]] +then err_exit "picked up file descriptor zero for opening script file" +fi +cat > close0 <<\! + for ((i=0; i < 1100; i++)) + do exec 4< /dev/null + read -u4 + done + exit 0 +! +./close0 2> /dev/null || err_exit "multiple exec 4< /dev/null can fail" +$SHELL -c ' + trap "rm -f in$$ out$$" EXIT + for ((i = 0; i < 1000; i++)) + do print -r -- "This is a test" + done > in$$ + > out$$ + exec 1<> out$$ + builtin cat + print -r -- "$(cat in$$)" + cmp -s in$$ out$$' 2> /dev/null +[[ $? == 0 ]] || err_exit 'builtin cat truncates files' +cat >| script <<-\! +print hello +( exec 3<&- 4<&-) +exec 3<&- 4<&- +print world +! +chmod +x script +[[ $( $SHELL ./script) == $'hello\nworld' ]] || err_exit 'closing 3 & 4 causes script to fail' +cd ~- || err_exit "cd back failed" +( exec > '' ) 2> /dev/null && err_exit '> "" does not fail' +unset x +( exec > ${x} ) 2> /dev/null && err_exit '> $x, where x null does not fail' +exec <<! +foo +bar +! +( exec 0< /dev/null) +read line +if [[ $line != foo ]] +then err_exit 'file descriptor not restored after exec in subshell' +fi +exec 3>&- 4>&-; cd /; rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed" +[[ $( { + read -r line;print -r -- "$line" + ( + read -r line;print -r -- "$line" + ) & wait + while read -r line + do print -r -- "$line" + done + } << ! +line 1 +line 2 +line 3 +!) == $'line 1\nline 2\nline 3' ]] || err_exit 'read error with subshells' +# 2004-05-11 bug fix +cat > /tmp/io$$.1 <<- \++EOF++ + script=/tmp/io$$.2 + trap 'rm -f $script' EXIT + exec 9> $script + for ((i=3; i<9; i++)) + do eval "while read -u$i; do : ;done $i</dev/null" + print -u9 "exec $i< /dev/null" + done + for ((i=0; i < 60; i++)) + do print -u9 -f "%.80c\n" ' ' + done + print -u9 'print ok' + exec 9<&- + chmod +x $script + $script +++EOF++ +chmod +x /tmp/io$$.1 +[[ $($SHELL /tmp/io$$.1) == ok ]] || err_exit "parent i/o causes child script to fail" +rm -rf /tmp/io$$.[12] +# 2004-11-25 ancient /dev/fd/NN redirection bug fix +x=$( + { + print -n 1 + print -n 2 > /dev/fd/2 + print -n 3 + print -n 4 > /dev/fd/2 + } 2>&1 +) +[[ $x == "1234" ]] || err_exit "/dev/fd/NN redirection fails to dup" +# 2004-12-20 redirction loss bug fix +cat > /tmp/io$$.1 <<- \++EOF++ + function a + { + trap 'print ok' EXIT + : > /dev/null + } + a +++EOF++ +chmod +x /tmp/io$$.1 +[[ $(/tmp/io$$.1) == ok ]] || err_exit "trap on EXIT loses last command redirection" +print > /dev/null {n}> /tmp/io$$.1 +[[ ! -s /tmp/io$$.1 ]] && newio=1 +rm -rf /tmp/io$$.1 +if [[ $newio && $(print hello | while read -u$n; do print $REPLY; done {n}<&0) != hello ]] +then err_exit "{n}<&0 not working with for loop" +fi +[[ $({ read -r;read -u3 3<&0; print -- "$REPLY" ;} <<! +hello +world +!) == world ]] || err_exit 'I/O not synchronized with <&' +trap 'rm -f /tmp/seek$$; exit $((Errors+1))' EXIT +x="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNSPQRSTUVWXYZ1234567890" +for ((i=0; i < 62; i++)) +do printf "%.39c\n" ${x:i:1} +done > /tmp/seek$$ +if command exec 3<> /tmp/seek$$ +then (( $(3<#) == 0 )) || err_exit "not at position 0" + (( $(3<# ((EOF))) == 40*62 )) || err_exit "not at end-of-file" + command exec 3<# ((40*8)) || err_exit "absolute seek fails" + read -u3 + [[ $REPLY == +(i) ]] || err_exit "expecting iiii..." + [[ $(3<#) == $(3<# ((CUR)) ) ]] || err_exit '$(3<#)!=$(3<#((CUR)))' + command exec 3<# ((CUR+80)) + read -u3 + [[ $REPLY == {39}(l) ]] || err_exit "expecting lll..." + command exec 3<# ((EOF-80)) + read -u3 + [[ $REPLY == +(9) ]] || err_exit "expecting 999...; got $REPLY" + command exec 3># ((80)) + print -u3 -f "%.39c\n" @ + command exec 3># ((80)) + read -u3 + [[ $REPLY == +(@) ]] || err_exit "expecting @@@..." + read -u3 + [[ $REPLY == +(d) ]] || err_exit "expecting ddd..." + command exec 3># ((EOF)) + print -u3 -f "%.39c\n" ^ + (( $(3<# ((CUR-0))) == 40*63 )) || err_exit "not at extended end-of-file" + command exec 3<# ((40*62)) + read -u3 + [[ $REPLY == +(^) ]] || err_exit "expecting ddd..." + command exec 3<# ((0)) + command exec 3<# *jjjj* + read -u3 + [[ $REPLY == {39}(j) ]] || err_exit "<# pattern failed" + [[ $(command exec 3<## *llll*) = {39}(k) ]] || err_exit "<## pattern not saving standard output" + read -u3 + [[ $REPLY == {39}(l) ]] || err_exit "<## pattern failed to position" + command exec 3<# *abc* + read -u3 && err_exit "not found pattern not positioning at eof" + cat /tmp/seek$$ | read -r <# *WWW* + [[ $REPLY == *WWWWW* ]] || err_exit '<# not working for pipes' +else err_exit "/tmp/seek$$: cannot open for reading" +fi +trap "" EXIT +rm -f /tmp/seek$$ +$SHELL -ic ' +{ + print -u2 || exit 2 + print -u3 || exit 3 + print -u4 || exit 4 + print -u5 || exit 5 + print -u6 || exit 6 + print -u7 || exit 7 + print -u8 || exit 8 + print -u9 || exit 9 +} 3> /dev/null 4> /dev/null 5> /dev/null 6> /dev/null 7> /dev/null 8> /dev/null 9> /dev/null' > /dev/null 2>&1 +exitval=$? +(( exitval )) && err_exit "print to unit $exitval failed" +trap 'rm -rf /tmp/io.sh$$*' EXIT +$SHELL -c "{ > /tmp/io.sh$$.1 ; date;} >&- 2> /dev/null" > /tmp/io.sh$$.2 +[[ -s /tmp/io.sh$$.1 || -s /tmp/io.sh$$.2 ]] && err_exit 'commands with standard output closed produce output' +$SHELL -c "$SHELL -c ': 3>&1' 1>&- 2>/dev/null" && err_exit 'closed standard output not passed to subshell' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/nameref.sh b/usr/src/lib/libshell/common/tests/nameref.sh new file mode 100644 index 0000000000..a6c52ddaa8 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/nameref.sh @@ -0,0 +1,229 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +function checkref +{ + nameref foo=$1 bar=$2 + if [[ $foo != $bar ]] + then err_exit "foo=$foo != bar=$bar" + fi + foo=hello + if [[ $foo != $bar ]] + then err_exit "foo=$foo != bar=$bar" + fi + foo.child=child + if [[ ${foo.child} != ${bar.child} ]] + then err_exit "foo.child=${foo.child} != bar=${bar.child}" + fi +} + +name=first +checkref name name +name.child=second +checkref name name +.foo=top +.foo.bar=next +checkref .foo.bar .foo.bar +if [[ ${.foo.bar} != hello ]] +then err_exit ".foo.bar=${.foo.bar} != hello" +fi +if [[ ${.foo.bar.child} != child ]] +then err_exit ".foo.bar.child=${.foo.bar.child} != child" +fi +function func1 +{ + nameref color=$1 + func2 color +} + +function func2 +{ + nameref color=$1 + set -s -- ${!color[@]} + print -r -- "$@" +} + +typeset -A color +color[apple]=red +color[grape]=purple +color[banana]=yellow +if [[ $(func1 color) != 'apple banana grape' ]] +then err_exit "nameref or nameref not working" +fi +nameref x=.foo.bar +if [[ ${!x} != .foo.bar ]] +then err_exit "${!x} not working" +fi +typeset +n x $(typeset +n) +unset x +nameref x=.foo.bar +function x.set +{ + [[ ${.sh.value} ]] && print hello +} +if [[ $(.foo.bar.set) != $(x.set) ]] +then err_exit "function references not working" +fi +if [[ $(typeset +n) != x ]] +then err_exit "typeset +n doesn't list names of reference variables" +fi +if [[ $(typeset -n) != x=.foo.bar ]] +then err_exit "typeset +n doesn't list values of reference variables" +fi +file=/tmp/shtest$$ +typeset +n foo bar 2> /dev/null +unset foo bar +export bar=foo +nameref foo=bar +if [[ $foo != foo ]] +then err_exit "value of nameref foo != $foo" +fi +trap "rm -f $file" EXIT INT +cat > $file <<\! +print -r -- $foo +! +chmod +x "$file" +y=$( $file) +if [[ $y != '' ]] +then err_exit "reference variable not cleared" +fi +{ + command nameref xx=yy + command nameref yy=xx +} 2> /dev/null && err_exit "self reference not detected" +typeset +n foo bar +unset foo bar +set foo +nameref bar=$1 +foo=hello +if [[ $bar != hello ]] +then err_exit 'nameref of positional paramters outside of function not working' +fi +unset foo bar +bar=123 +function foobar +{ + typeset -n foo=bar + typeset -n foo=bar +} +foobar 2> /dev/null || err_exit 'nameref not unsetting previous reference' +( + nameref short=verylong + short=( A=a B=b ) + if [[ ${verylong.A} != a ]] + then err_exit 'nameref short to longname compound assignment error' + fi +) 2> /dev/null|| err_exit 'nameref short to longname compound assignment error' +unset x +if [[ $(var1=1 var2=2 + for i in var1 var2 + do nameref x=$i + print $x + done) != $'1\n2' ]] +then err_exit 'for loop nameref optimization error' +fi +if [[ $(typeset -A var1 var2 + var1[sub1]=1 var2[sub2]=1 + for i in var1 var2 + do + typeset -n array=$i + print ${!array[*]} + done) != $'sub1\nsub2' ]] +then err_exit 'for loop nameref optimization test2 error' +fi + +unset -n x foo bar +if [[ $(nameref x=foo;for x in foo bar;do print ${!x};done) != $'foo\nbar' ]] +then err_exit 'for loop optimization with namerefs not working' +fi +if [[ $( + p=(x=(r=3) y=(r=4)) + for i in x y + do nameref x=p.$i + print ${x.r} + done +) != $'3\n4' ]] +then err_exit 'nameref optimization error' +fi +[[ $( +unset x y var +var=(foo=bar) +for i in y var +do typeset -n x=$i + if [[ ${!x.@} ]] + then print ok + fi + typeset +n x +done) != ok ]] && err_exit 'invalid for loop optimization of name references' +function setval # name value +{ + nameref arg=$1 + nameref var=arg.bar + var=$2 +} +foo=( integer bar=0) +setval foo 5 +(( foo.bar == 5)) || err_exit 'nested nameref not working' +function selfref +{ + typeset -n ps=$1 + print -r -- "${ps}" +} +ps=(a=1 b=2) +[[ $(selfref ps) == *a=1* ]] || err_exit 'local nameref cannot reference global variable of the same name' +function subref +{ + typeset -n foo=$1 + print -r -- ${foo.a} +} +[[ $(subref ps) == 1 ]] || err_exit 'local nameref cannot reference global variable child' + +function local +{ + typeset ps=(typeset -i a=3 b=4) + [[ $(subref ps) == 3 ]] || err_exit 'local nameref cannot reference caller compound variable' +} +local +unset -f local +function local +{ + qs=(integer a=3; integer b=4) +} +local 2> /dev/null || err_exit 'function local has non-zero exit status' +[[ ${qs.a} == 3 ]] || err_exit 'function cannot set compound global variable' +unset fun i +foo=(x=hi) +function fun +{ + nameref i=$1 + print -r -- "${i.x}" +} +i=foo +[[ $(fun $i) == hi ]] || err_exit 'nameref for compound variable with in function name of caller fails' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/options.sh b/usr/src/lib/libshell/common/tests/options.sh new file mode 100644 index 0000000000..2520cb2a2e --- /dev/null +++ b/usr/src/lib/libshell/common/tests/options.sh @@ -0,0 +1,313 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +if [[ $( ${SHELL-ksh} -s hello<<-\! + print $1 + ! + ) != hello ]] +then err_exit "${SHELL-ksh} -s not working" +fi +x=$( + set -e + false && print bad + print good +) +if [[ $x != good ]] +then err_exit 'sh -e not workuing' +fi +[[ $($SHELL -D -c 'print hi; print $"hello"') == '"hello"' ]] || err_exit 'ksh -D not working' + +tmp=/tmp/ksh$$ +mkdir $tmp +rc=$tmp/.kshrc +print $'function env_hit\n{\n\tprint OK\n}' > $rc + +export ENV=$rc +if [[ -o privileged ]] +then + [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] && + err_exit 'privileged nointeractive shell reads $ENV file' + [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] && + err_exit 'privileged -E reads $ENV file' + [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] && + err_exit 'privileged +E reads $ENV file' + [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] && + err_exit 'privileged --rc reads $ENV file' + [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] && + err_exit 'privileged --norc reads $ENV file' +else + [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] && + err_exit 'nointeractive shell reads $ENV file' + [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] || + err_exit '-E ignores $ENV file' + [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] && + err_exit '+E reads $ENV file' + [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] || + err_exit '--rc ignores $ENV file' + [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] && + err_exit '--norc reads $ENV file' +fi + +export ENV= +if [[ -o privileged ]] +then + [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] && + err_exit 'privileged nointeractive shell reads $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] && + err_exit 'privileged -E ignores empty $ENV' + [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] && + err_exit 'privileged +E reads $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] && + err_exit 'privileged --rc ignores empty $ENV' + [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] && + err_exit 'privileged --norc reads $HOME/.kshrc file' +else + [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] && + err_exit 'nointeractive shell reads $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] && + err_exit '-E ignores empty $ENV' + [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] && + err_exit '+E reads $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] && + err_exit '--rc ignores empty $ENV' + [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] && + err_exit '--norc reads $HOME/.kshrc file' +fi + +unset ENV +if [[ -o privileged ]] +then + [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] && + err_exit 'privileged nointeractive shell reads $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] && + err_exit 'privileged -E reads $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] && + err_exit 'privileged +E reads $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] && + err_exit 'privileged --rc reads $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] && + err_exit 'privileged --norc reads $HOME/.kshrc file' +else + [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] && + err_exit 'nointeractive shell reads $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] || + err_exit '-E ignores $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] && + err_exit '+E reads $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] || + err_exit '--rc ignores $HOME/.kshrc file' + [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] && + err_exit '--norc reads $HOME/.kshrc file' +fi + +rm -rf $tmp + +if command set -G 2> /dev/null +then mkdir /tmp/ksh$$ + cd /tmp/ksh$$ + mkdir bar foo + > bar.c > bam.c + > bar/foo.c > bar/bam.c + > foo/bam.c + set -- **.c + expected='bam.c bar.c' + [[ $* == $expected ]] || + err_exit "-G **.c failed -- expected '$expected', got '$*'" + set -- ** + expected='bam.c bar bar.c bar/bam.c bar/foo.c foo foo/bam.c' + [[ $* == $expected ]] || + err_exit "-G ** failed -- expected '$expected', got '$*'" + set -- **/*.c + expected='bam.c bar.c bar/bam.c bar/foo.c foo/bam.c' + [[ $* == $expected ]] || + err_exit "-G **/*.c failed -- expected '$expected', got '$*'" + set -- **/bam.c + expected='bam.c bar/bam.c foo/bam.c' + [[ $* == $expected ]] || + err_exit "-G **/bam.c failed -- expected '$expected', got '$*'" + cd ~- + rm -rf /tmp/ksh$$ +fi + +mkdir /tmp/ksh$$ +cd /tmp/ksh$$ +t="<$$>.profile.<$$>" +echo "echo '$t'" > .profile +cp $SHELL ./-ksh +if [[ -o privileged ]] +then + [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] && + err_exit 'privileged -l reads .profile' + [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] && + err_exit 'privileged --login reads .profile' + [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>&1) == *$t* ]] && + err_exit 'privileged --login-shell reads .profile' + [[ $(HOME=$PWD $SHELL --login_shell </dev/null 2>&1) == *$t* ]] && + err_exit 'privileged --login_shell reads .profile' + [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>&1) == *$t* ]] && + err_exit 'privileged exec -a -ksh ksh reads .profile' + [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] && + err_exit 'privileged ./-ksh reads .profile' + [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] && + err_exit 'privileged ./-ksh -p reads .profile' +else + [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] || + err_exit '-l ignores .profile' + [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] || + err_exit '--login ignores .profile' + [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>&1) == *$t* ]] || + err_exit '--login-shell ignores .profile' + [[ $(HOME=$PWD $SHELL --login_shell </dev/null 2>&1) == *$t* ]] || + err_exit '--login_shell ignores .profile' + [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>&1) == *$t* ]] || + err_exit 'exec -a -ksh ksh ignores .profile' + [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] || + err_exit './-ksh ignores .profile' + [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] && + err_exit './-ksh -p does not ignore .profile' +fi +cd ~- +rm -rf /tmp/ksh$$ + + +# { exec interactive login_shell restricted xtrace } in the following test + +for opt in \ + allexport all-export all_export \ + bgnice bg-nice bg_nice \ + clobber emacs \ + errexit err-exit err_exit \ + glob \ + globstar glob-star glob_star \ + gmacs \ + ignoreeof ignore-eof ignore_eof \ + keyword log markdirs monitor notify \ + pipefail pipe-fail pipe_fail \ + trackall track-all track_all \ + unset verbose vi \ + viraw vi-raw vi_raw +do old=$opt + if [[ ! -o $opt ]] + then old=no$opt + fi + + set --$opt || err_exit "set --$opt failed" + [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" + [[ -o no$opt ]] && err_exit "[[ -o no$opt ]] failed" + [[ -o no-$opt ]] && err_exit "[[ -o no-$opt ]] failed" + [[ -o no_$opt ]] && err_exit "[[ -o no_$opt ]] failed" + [[ -o ?$opt ]] || err_exit "[[ -o ?$opt ]] failed" + [[ -o ?no$opt ]] || err_exit "[[ -o ?no$opt ]] failed" + [[ -o ?no-$opt ]] || err_exit "[[ -o ?no-$opt ]] failed" + [[ -o ?no_$opt ]] || err_exit "[[ -o ?no_$opt ]] failed" + + set --no$opt || err_exit "set --no$opt failed" + [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" + [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed" + + set --no-$opt || err_exit "set --no-$opt failed" + [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" + [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed" + + set --no_$opt || err_exit "set --no_$opt failed" + [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" + [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed" + + set -o $opt || err_exit "set -o $opt failed" + [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" + set -o $opt=1 || err_exit "set -o $opt=1 failed" + [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" + set -o no$opt=0 || err_exit "set -o no$opt=0 failed" + [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" + set --$opt=1 || err_exit "set --$opt=1 failed" + [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" + set --no$opt=0 || err_exit "set --no$opt=0 failed" + [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" + + set -o no$opt || err_exit "set -o no$opt failed" + [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" + set -o $opt=0 || err_exit "set -o $opt=0 failed" + [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" + set -o no$opt=1 || err_exit "set -o no$opt=1 failed" + [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" + set --$opt=0 || err_exit "set --$opt=0 failed" + [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" + set --no$opt=1 || err_exit "set --no$opt=1 failed" + [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" + + set -o no-$opt || err_exit "set -o no-$opt failed" + [[ -o no-$opt ]] || err_exit "[[ -o no-$opt ]] failed" + + set -o no_$opt || err_exit "set -o no_$opt failed" + [[ -o no_$opt ]] || err_exit "[[ -o no_$opt ]] failed" + + set +o $opt || err_exit "set +o $opt failed" + [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed" + + set +o no$opt || err_exit "set +o no$opt failed" + [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" + + set +o no-$opt || err_exit "set +o no-$opt failed" + [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" + + set +o no_$opt || err_exit "set +o no_$opt failed" + [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed" + + set --$old +done + +for opt in \ + exec interactive login_shell login-shell logi privileged \ + rc restricted xtrace +do [[ -o $opt ]] + y=$? + [[ -o no$opt ]] + n=$? + case $y$n in + 10|01) ;; + *) err_exit "[[ -o $opt ]] == [[ -o no$opt ]]" ;; + esac +done + +for opt in \ + foo foo-bar foo_bar +do if [[ -o ?$opt ]] + then err_exit "[[ -o ?$opt ]] should fail" + fi + if [[ -o ?no$opt ]] + then err_exit "[[ -o ?no$opt ]] should fail" + fi +done +false | true | true || err_exit 'pipe not exiting exit value of last element' +true | true | false && err_exit 'pipe not exiting false' +set -o pipefail +false | true | true && err_exit 'pipe with first not failing with pipefail' +true | false | true && err_exit 'pipe middle not failing with pipefail' +true | true | false && err_exit 'pipe last not failing with pipefail' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/path.sh b/usr/src/lib/libshell/common/tests/path.sh new file mode 100644 index 0000000000..7083aca713 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/path.sh @@ -0,0 +1,186 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +mkdir /tmp/ksh$$ +cd /tmp/ksh$$ +trap "PATH=$PATH; cd /; rm -rf /tmp/ksh$$" EXIT +(PATH="/bin") +[[ $($SHELL -c 'print -r -- "$PATH"') == "$PATH" ]] || err_exit 'export PATH lost in subshell' +cat > bug1 <<- \EOF + print print ok > /tmp/ok$$ + /bin/chmod 755 /tmp/ok$$ + trap 'cd /; rm -f /tmp/ok$$' EXIT + function a + { + typeset -x PATH=/tmp + ok$$ + } + path=$PATH + unset PATH + a + PATH=$path +} +EOF +[[ $($SHELL ./bug1 2> /dev/null) == ok ]] || err_exit "PATH in function not working" +cat > bug1 <<- \EOF + function lock_unlock + { + typeset PATH=/usr/bin + typeset -x PATH='' + } + + PATH=/usr/bin + : $(PATH=/usr/bin getconf PATH) + typeset -ft lock_unlock + lock_unlock +EOF +($SHELL ./bug1) 2> /dev/null || err_exit "path_delete bug" +mkdir tdir$$ +if $SHELL tdir$$ > /dev/null 2>&1 +then err_exit 'not an error to run ksh on a directory' +fi + +print 'print hi' > ls +if [[ $($SHELL ls 2> /dev/null) != hi ]] +then err_exit "$SHELL name not executing version in current directory" +fi +if [[ $(ls -d . 2>/dev/null) == . && $(PATH=/bin:/usr/bin:$PATH ls -d . 2>/dev/null) != . ]] +then err_exit 'PATH export in command substitution not working' +fi +pwd=$PWD +# get rid of leading and trailing : and trailing :. +PATH=${PATH%.} +PATH=${PATH%:} +PATH=${PATH#.} +PATH=${PATH#:} +path=$PATH +var=$(whence date) +dir=$(basename "$var") +for i in 1 2 3 4 5 6 7 8 9 0 +do if ! whence notfound$i 2> /dev/null + then cmd=notfound$i + break + fi +done +print 'print hello' > date +chmod +x date +print 'print notfound' > $cmd +chmod +x "$cmd" +> foo +chmod 755 foo +for PATH in $path :$path $path: .:$path $path: $path:. $PWD::$path $PWD:.:$path $path:$PWD $path:.:$PWD +do +# print path=$PATH $(whence date) +# print path=$PATH $(whence "$cmd") + date + "$cmd" +done > /dev/null 2>&1 +builtin -d date 2> /dev/null +if [[ $(PATH=:/usr/bin; date) != 'hello' ]] +then err_exit "leading : in path not working" +fi +( + PATH=$PWD: + builtin chmod + print 'print cannot execute' > noexec + chmod 644 noexec + if [[ ! -x noexec ]] + then noexec > /dev/null 2>&1 + else exit 126 + fi +) +status=$? +[[ $status == 126 ]] || err_exit "exit status of non-executable is $status -- 126 expected" +builtin -d rm 2> /dev/null +rm=$(whence rm) +d=$(dirname "$rm") +unset FPATH +PATH=/dev/null +if date > /dev/null 2>&1 +then err_exit 'programs in . should not be found' +fi +[[ $(whence ./foo) != "$PWD/"./foo ]] && err_exit 'whence ./foo not working' +[[ $(whence "$PWD/foo") != "$PWD/foo" ]] && err_exit 'whence $PWD/foo not working' +[[ $(whence ./xxxxx) ]] && err_exit 'whence ./xxxx not working' +PATH=$d: +cp "$rm" kshrm$$ +if [[ $(whence kshrm$$) != $PWD/kshrm$$ ]] +then err_exit 'trailing : in pathname not working' +fi +cp "$rm" rm +PATH=:$d +if [[ $(whence rm) != $PWD/rm ]] +then err_exit 'leading : in pathname not working' +fi +PATH=$d: whence rm > /dev/null +if [[ $(whence rm) != $PWD/rm ]] +then err_exit 'pathname not restored after scoping' +fi +mkdir bin +print 'print ok' > bin/tst +chmod +x bin/tst +if [[ $(PATH=$PWD/bin tst 2>/dev/null) != ok ]] +then err_exit '(PATH=$PWD/bin foo) does not find $PWD/bin/foo' +fi +cd / +if whence ls > /dev/null +then PATH= + if [[ $(whence rm) ]] + then err_exit 'setting PATH to Null not working' + fi + unset PATH + if [[ $(whence rm) != /*rm ]] + then err_exit 'unsetting path not working' + fi +fi +PATH=/dev:/tmp/ksh$$ +x=$(whence rm) +typeset foo=$(PATH=/xyz:/abc :) +y=$(whence rm) +[[ $x != "$y" ]] && err_exit 'PATH not restored after command substitution' +whence getconf > /dev/null && err_exit 'getconf should not be found' +builtin /bin/getconf +PATH=/bin +PATH=$(getconf PATH) +x=$(whence ls) +PATH=.:$PWD:${x%/ls} +[[ $(whence ls) == "$x" ]] || err_exit 'PATH search bug when .:$PWD in path' +PATH=$PWD:.:${x%/ls} +[[ $(whence ls) == "$x" ]] || err_exit 'PATH search bug when :$PWD:. in path' +cd "${x%/ls}" +[[ $(whence ls) == /* ]] || err_exit 'whence not generating absolute pathname' +status=$($SHELL -c $'trap \'print $?\' EXIT;/a/b/c/d/e 2> /dev/null') +[[ $status == 127 ]] || err_exit "not found command exit status $status -- expected 127" +status=$($SHELL -c $'trap \'print $?\' EXIT;/dev/null 2> /dev/null') +[[ $status == 126 ]] || err_exit "non executable command exit status $status -- expected 126" +status=$($SHELL -c $'trap \'print $?\' ERR;/a/b/c/d/e 2> /dev/null') +[[ $status == 127 ]] || err_exit "not found command with ERR trap exit status $status -- expected 127" +status=$($SHELL -c $'trap \'print $?\' ERR;/dev/null 2> /dev/null') +[[ $status == 126 ]] || err_exit "non executable command ERR trap exit status $status -- expected 126" +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/quoting.sh b/usr/src/lib/libshell/common/tests/quoting.sh new file mode 100644 index 0000000000..9a9e23bd55 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/quoting.sh @@ -0,0 +1,331 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +if [[ 'hi there' != "hi there" ]] +then err_exit "single quotes not the same as double quotes" +fi +x='hi there' +if [[ $x != 'hi there' ]] +then err_exit "$x not the same as 'hi there'" +fi +if [[ $x != "hi there" ]] +then err_exit "$x not the same as \"hi there \"" +fi +if [[ \a\b\c\*\|\"\ \\ != 'abc*|" \' ]] +then err_exit " \\ differs from '' " +fi +if [[ "ab\'\"\$(" != 'ab\'\''"$(' ]] +then err_exit " \"\" differs from '' " +fi +if [[ $(print -r - 'abc*|" \') != 'abc*|" \' ]] +then err_exit "\$(print -r - '') differs from ''" +fi +if [[ $(print -r - "abc*|\" \\") != 'abc*|" \' ]] +then err_exit "\$(print -r - '') differs from ''" +fi +if [[ "$(print -r - 'abc*|" \')" != 'abc*|" \' ]] +then err_exit "\"\$(print -r - '')\" differs from ''" +fi +if [[ "$(print -r - "abc*|\" \\")" != 'abc*|" \' ]] +then err_exit "\"\$(print -r - "")\" differs from ''" +fi +if [[ $(print -r - $(print -r - 'abc*|" \')) != 'abc*|" \' ]] +then err_exit "nested \$(print -r - '') differs from ''" +fi +if [[ "$(print -r - $(print -r - 'abc*|" \'))" != 'abc*|" \' ]] +then err_exit "\"nested \$(print -r - '')\" differs from ''" +fi +if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]] +then err_exit "nested \"\$(print -r - '')\" differs from ''" +fi +unset x +if [[ ${x-$(print -r - "abc*|\" \\")} != 'abc*|" \' ]] +then err_exit "\${x-\$(print -r - '')} differs from ''" +fi +if [[ ${x-$(print -r - "a}c*|\" \\")} != 'a}c*|" \' ]] +then err_exit "\${x-\$(print -r - '}')} differs from ''" +fi +x=$((echo foo)|(cat)) +if [[ $x != foo ]] +then err_exit "((cmd)|(cmd)) failed" +fi +x=$(print -r -- "\"$HOME\"") +if [[ $x != '"'$HOME'"' ]] +then err_exit "nested double quotes failed" +fi +: ${z="a{b}c"} +if [[ $z != 'a{b}c' ]] +then err_exit '${z="a{b}c"} not correct' +fi +unset z +: "${z="a{b}c"}" +if [[ $z != 'a{b}c' ]] +then err_exit '"${z="a{b}c"}" not correct' +fi +if [[ $(print -r -- "a\*b") != 'a\*b' ]] +then err_exit '$(print -r -- "a\*b") differs from a\*b' +fi +unset x +if [[ $(print -r -- "a\*b$x") != 'a\*b' ]] +then err_exit '$(print -r -- "a\*b$x") differs from a\*b' +fi +x=hello +set -- ${x+foo bar bam} +if (( $# !=3 )) +then err_exit '${x+foo bar bam} does not yield three arguments' +fi +set -- ${x+foo "bar bam"} +if (( $# !=2 )) +then err_exit '${x+foo "bar bam"} does not yield two arguments' +fi +set -- ${x+foo 'bar bam'} +if (( $# !=2 )) +then err_exit '${x+foo '\''bar bam'\''} does not yield two arguments' +fi +set -- ${x+foo $x bam} +if (( $# !=3 )) +then err_exit '${x+foo $x bam} does not yield three arguments' +fi +set -- ${x+foo "$x" bam} +if (( $# !=3 )) +then err_exit '${x+foo "$x" bam} does not yield three arguments' +fi +set -- ${x+"foo $x bam"} +if (( $# !=1 )) +then err_exit '${x+"foo $x bam"} does not yield one argument' +fi +set -- "${x+foo $x bam}" +if (( $# !=1 )) +then err_exit '"${x+foo $x bam}" does not yield one argument' +fi +set -- ${x+foo "$x "bam} +if (( $# !=2 )) +then err_exit '${x+foo "$x "bam} does not yield two arguments' +fi +x="ab$'cd" +if [[ $x != 'ab$'"'cd" ]] +then err_exit '$'"' inside double quotes not working" +fi +x=`print 'ab$'` +if [[ $x != 'ab$' ]] +then err_exit '$'"' inside `` quotes not working" +fi +unset a +x=$(print -r -- "'\ +\ +") +if [[ $x != "'" ]] +then err_exit 'line continuation in double strings not working' +fi +x=$(print -r -- "'\ +$a\ +") +if [[ $x != "'" ]] +then err_exit 'line continuation in expanded double strings not working' +fi +x='\*' +if [[ $(print -r -- $x) != '\*' ]] +then err_exit 'x="\\*";$x != \*' +fi +x=' hello world ' +set -- $x +if (( $# != 2 )) +then err_exit 'field splitting error' +fi +x=$(print -r -- '1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890 \ +1234567890123456789012345678901234567890123456789012345678901234567890') +if (( ${#x} != (15*73-3) )) +then err_exit "length of x, ${#x}, is incorrect should be $((15*73-3))" +fi +x='$hi' +if [[ $x\$ != '$hi$' ]] +then err_exit ' $x\$, with x=$hi, does not expand to $hi$' +fi +if [[ $x$ != '$hi$' ]] +then err_exit ' $x$, with x=$hi, does not expand to $hi$' +fi +set -- $(/bin/echo foo;sleep 1;/bin/echo bar) +if [[ $# != 2 ]] +then err_exit 'word splitting after command substitution not working' +fi +unset q +if [[ "${q:+'}q${q:+'}" != q ]] +then err_exit 'expansion of "{q:+'\''}" not correct when q unset' +fi +q=1 +if [[ "${q:+'}q${q:+'}" != "'q'" ]] +then err_exit 'expansion of "{q:+'\''}" not correct when q set' +fi +x=$'x\' #y' +if [[ $x != "x' #y" ]] +then err_exit "$'x\' #y'" not working +fi +x=$q$'x\' #y' +if [[ $x != "1x' #y" ]] +then err_exit "$q$'x\' #y'" not working +fi +IFS=, +x='a,b\,c,d' +set -- $x +if [[ $2 != 'b\' ]] +then err_exit "field splitting of $x with IFS=$IFS not working" +fi +foo=bar +bar=$(print -r -- ${foo+\\n\ }) +if [[ $bar != '\n ' ]] +then err_exit '${foo+\\n\ } expansion error' +fi +unset bar +bar=$(print -r -- ${foo+\\n\ $bar}) +if [[ $bar != '\n ' ]] +then err_exit '${foo+\\n\ $bar} expansion error with bar unset' +fi +x='\\(..\\)|&\|\|\\&\\|' +if [[ $(print -r -- $x) != "$x" ]] +then err_exit '$x, where x=\\(..\\)|&\|\|\\&\\| not working' +fi +x='\\(' +if [[ $(print -r -- a${x}b) != a"${x}"b ]] +then err_exit 'a${x}b, where x=\\( not working' +fi +x= +if [[ $(print -r -- $x'\\1') != '\\1' ]] +then err_exit 'backreference inside single quotes broken' +fi +set -- '' +set -- "$@" +if (( $# != 1 )) +then err_exit '"$@" not preserving nulls' +fi +x= +if [[ $(print -r s"!\2${x}\1\a!") != 's!\2\1\a!' ]] +then err_exit 'print -r s"!\2${x}\1\a!" not equal s!\2\1\a!' +fi +if [[ $(print -r $'foo\n\n\n') != foo ]] +then err_exit 'trailing newlines on comsubstitution not removed' +fi +unset x +if [[ ${x:='//'} != '//' ]] +then err_exit '${x:='//'} != "//"' +fi +if [[ $(print -r "\"hi$\"") != '"hi$"' ]] +then err_exit '$\ not correct inside ""' +fi +unset x +if [[ "${x-a\}b}" != 'a}b' ]] +then err_exit '"${x-a\}b}" != "a}b"' +fi +if [[ "\}\]$x\*\{\[\\" != '\}\]\*\{\[\' ]] +then err_exit '"\}\]$x\*\{\[\\" != "\}\]\*\{\[\"' +fi +foo=yes +if [[ $(print -r -- {\$foo}) != '{$foo}' ]] +then err_exit '{\$foo}' not expanded correctly +fi +[[ foo == $( +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +########################################################### +print foo) ]] || err_exit "command subsitution with long comments broken" +subject='some/other/words' +re='(?*)/(?*)/(?*)' +[[ ${subject/${re}/\3} != words ]] && err_exit 'string replacement with \3 not working' +[[ ${subject/${re}/'\3'} != '\3' ]] && err_exit 'string replacement with '"'\3'"' not working' +[[ ${subject/${re}/"\\3"} != '\3' ]] && err_exit 'string replacement with "\\3" not working' +[[ ${subject/${re}/"\3"} != '\3' ]] && err_exit 'string replacement with "\3" not working' +string='\3' +[[ ${subject/${re}/${string}} != words ]] && err_exit 'string replacement with $string not working with string=\3' +[[ $(print -r "${subject/${re}/${string}}") != words ]] && err_exit 'string replacement with $string not working with string=\3 using print' +[[ ${subject/${re}/"${string}"} != '\3' ]] && err_exit 'string replacement with "$string" not working with string=\3' +[[ $(print -r "${subject/${re}/"${string}"}") != '\3' ]] && err_exit 'string replacement with "$string" not working with string=\3 using print' +string='\\3' +[[ ${subject/${re}/${string}} != '\3' ]] && err_exit 'string replacement with $string not working with string=\\3' +[[ ${subject/${re}/"${string}"} != '\\3' ]] && err_exit 'string replacement with "$string" not working with string=\\3' +[[ ${subject/${re}/\4} != '\4' ]] && err_exit 'string replacement with \4 not working' +[[ ${subject/${re}/'\4'} != '\4' ]] && err_exit 'string replacement with '\4' not working' +string='\4' +[[ ${subject/${re}/${string}} != '\4' ]] && err_exit 'string replacement with $string not working with string=\4' +[[ ${subject/${re}/"${string}"} != '\4' ]] && err_exit 'string replacement with "$string" not working with string=\4' +string='&foo' +[[ ${subject/${re}/${string}} != '&foo' ]] && err_exit 'string replacement with $string not working with string=&foo' +[[ ${subject/${re}/"${string}"} != '&foo' ]] && err_exit 'string replacement with "$string" not working with string=&foo' +{ +x=x +x=${x:-`id | sed 's/^[^(]*(\([^)]*\)).*/\1/'`} +} 2> /dev/null || err_exit 'skipping over `` failed' +[[ $x == x ]] || err_exit 'assignment ${x:=`...`} failed' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/quoting2.sh b/usr/src/lib/libshell/common/tests/quoting2.sh new file mode 100644 index 0000000000..0532f72d7a --- /dev/null +++ b/usr/src/lib/libshell/common/tests/quoting2.sh @@ -0,0 +1,200 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +set -o noglob +if [[ 'hi there' != "hi there" ]] +then err_exit "single quotes not the same as double quotes" +fi +x='hi there' +if [[ $x != 'hi there' ]] +then err_exit "$x not the same as 'hi there'" +fi +if [[ $x != "hi there" ]] +then err_exit "$x not the same as \"hi there \"" +fi +if [[ \a\b\c\*\|\"\ \\ != 'abc*|" \' ]] +then err_exit " \\ differs from '' " +fi +if [[ "ab\'\"\$(" != 'ab\'\''"$(' ]] +then err_exit " \"\" differs from '' " +fi +if [[ $(print -r - 'abc*|" \') != 'abc*|" \' ]] +then err_exit "\$(print -r - '') differs from ''" +fi +if [[ $(print -r - "abc*|\" \\") != 'abc*|" \' ]] +then err_exit "\$(print -r - '') differs from ''" +fi +if [[ "$(print -r - 'abc*|" \')" != 'abc*|" \' ]] +then err_exit "\"\$(print -r - '')\" differs from ''" +fi +if [[ "$(print -r - "abc*|\" \\")" != 'abc*|" \' ]] +then err_exit "\"\$(print -r - "")\" differs from ''" +fi +if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]] +then err_exit "nested \$(print -r - '') differs from ''" +fi +if [[ "$(print -r - $(print -r - 'abc*|" \'))" != 'abc*|" \' ]] +then err_exit "\"nested \$(print -r - '')\" differs from ''" +fi +if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]] +then err_exit "nested \"\$(print -r - '')\" differs from ''" +fi +unset x +if [[ ${x-$(print -r - "abc*|\" \\")} != 'abc*|" \' ]] +then err_exit "\${x-\$(print -r - '')} differs from ''" +fi +if [[ ${x-$(print -r - "a}c*|\" \\")} != 'a}c*|" \' ]] +then err_exit "\${x-\$(print -r - '}')} differs from ''" +fi +x=$((echo foo)|(cat)) +if [[ $x != foo ]] +then err_exit "((cmd)|(cmd)) failed" +fi +x=$(print -r -- "\"$HOME\"") +if [[ $x != '"'$HOME'"' ]] +then err_exit "nested double quotes failed" +fi +: ${z="a{b}c"} +if [[ $z != 'a{b}c' ]] +then err_exit '${z="a{b}c"} not correct' +fi +unset z +: "${z="a{b}c"}" +if [[ $z != 'a{b}c' ]] +then err_exit '"${z="a{b}c"}" not correct' +fi +if [[ $(print -r -- "a\*b") != 'a\*b' ]] +then err_exit '$(print -r -- "a\*b") differs from a\*b' +fi +unset x +if [[ $(print -r -- "a\*b$x") != 'a\*b' ]] +then err_exit '$(print -r -- "a\*b$x") differs from a\*b' +fi +x=hello +set -- ${x+foo bar bam} +if (( $# !=3 )) +then err_exit '${x+foo bar bam} does not yield three arguments' +fi +set -- ${x+foo "bar bam"} +if (( $# !=2 )) +then err_exit '${x+foo "bar bam"} does not yield two arguments' +fi +set -- ${x+foo 'bar bam'} +if (( $# !=2 )) +then err_exit '${x+foo '\''bar bam'\''} does not yield two arguments' +fi +set -- ${x+foo $x bam} +if (( $# !=3 )) +then err_exit '${x+foo $x bam} does not yield three arguments' +fi +set -- ${x+foo "$x" bam} +if (( $# !=3 )) +then err_exit '${x+foo "$x" bam} does not yield three arguments' +fi +set -- ${x+"foo $x bam"} +if (( $# !=1 )) +then err_exit '${x+"foo $x bam"} does not yield one argument' +fi +set -- "${x+foo $x bam}" +if (( $# !=1 )) +then err_exit '"${x+foo $x bam}" does not yield one argument' +fi +set -- ${x+foo "$x "bam} +if (( $# !=2 )) +then err_exit '${x+foo "$x "bam} does not yield two arguments' +fi +x="ab$'cd" +if [[ $x != 'ab$'"'cd" ]] +then err_exit '$'"' inside double quotes not working" +fi +x=`print 'ab$'` +if [[ $x != 'ab$' ]] +then err_exit '$'"' inside `` quotes not working" +fi +unset a +x=$(print -r -- "'\ +\ +") +if [[ $x != "'" ]] +then err_exit 'line continuation in double strings not working' +fi +x=$(print -r -- "'\ +$a\ +") +if [[ $x != "'" ]] +then err_exit 'line continuation in expanded double strings not working' +fi +x='\*' +if [[ $(print -r -- $x) != '\*' ]] +then err_exit 'x="\\*";$x != \*' +fi +if [[ $(print -r -- "\}" ) != '\}' ]] +then err_exit '(print -r -- "\}"' not working +fi +if [[ $(print -r -- "\{" ) != '\{' ]] +then err_exit 'print -r -- "\{"' not working +fi +# The following caused a syntax error on earlier versions +foo=foo x=- +if [[ `eval print \\${foo$x}` != foo* ]] +then err_exit '`eval print \\${foo$x}`' not working +fi +if [[ "`eval print \\${foo$x}`" != foo* ]] +then err_exit '"`eval print \\${foo$x}`"' not working +fi +if ( [[ $() != '' ]] ) +then err_exit '$() not working' +fi +x=a:b:c +set -- $( IFS=:; print $x) +if (( $# != 3)) +then err_exit 'IFS not working correctly with command substitution' +fi +$SHELL -n 2> /dev/null << \! || err_exit '$(...) bug with ( in comment' +y=$( + # ( this line is a bug fix + print hi +) +! +x= +for j in glob noglob +do for i in 'a\*b' 'a\ b' 'a\bc' 'a\*b' 'a\"b' + do eval [[ '$('print -r -- \'$i\'\$x')' != "'$i'" ]] && err_exit "quoting of $i\$x with $j enabled failed" + eval [[ '$('print -r -- \'$i\'\${x%*}')' != "'$i'" ]] && err_exit "quoting of $i\${x%*} with $j enabled failed" + if [[ $j == noglob ]] + then eval [[ '$('print -r -- \'$i\'\${x:-*}')' != "'$i''*'" ]] && err_exit "quoting of $i\${x:-*} with $j enabled failed" + fi + done + set -f +done +foo=foo +[[ "$" == '$' ]] || err_exit '"$" != $' +[[ "${foo}$" == 'foo$' ]] || err_exit 'foo=foo;"${foo}$" != foo$' +[[ "${foo}${foo}$" == 'foofoo$' ]] || err_exit 'foo=foo;"${foo}${foo}$" != foofoo$' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/return.sh b/usr/src/lib/libshell/common/tests/return.sh new file mode 100644 index 0000000000..b3ee5b11ff --- /dev/null +++ b/usr/src/lib/libshell/common/tests/return.sh @@ -0,0 +1,177 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +# test the behavior of return and exit with functions + +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +foo=NOVAL bar=NOVAL +file=/tmp/shtest$$ +trap "rm -f $file" EXIT INT +function foo +{ + typeset foo=NOEXIT + trap "foo=EXIT;rm -f $file" EXIT + > $file + if (( $1 == 0 )) + then return $2 + elif (( $1 == 1 )) + then exit $2 + else bar "$@" + fi +} + +function bar +{ + typeset bar=NOEXIT + trap 'bar=EXIT' EXIT + if (( $1 == 2 )) + then return $2 + elif (( $1 == 3 )) + then exit $2 + fi +} + +function funcheck +{ + [[ $foo = EXIT ]] || err_exit "foo "$@" : exit trap not set" + if [[ -f $file ]] + then rm -r $file + err_exit "foo $@: doesn't remove $file" + fi + foo=NOVAL bar=NOVAL +} + +(exit 0) || err_exit "exit 0 is not zero" +(return 0) || err_exit "return 0 is not zero" +(exit) || err_exit "default exit value is not zero" +(return) || err_exit "default return value is not zero" +(exit 35) +ret=$? +if (( $ret != 35 )) +then err_exit "exit 35 is $ret not 35" +fi +(return 35) +ret=$? +if (( $ret != 35 )) +then err_exit "return 35 is $ret not 35" +fi + +foo 0 0 || err_exit "foo 0 0: incorrect return" +funcheck 0 0 +foo 0 3 +ret=$? +if (( $ret != 3 )) +then err_exit "foo 0 3: return is $ret not 3" +fi +funcheck 0 3 +foo 2 0 || err_exit "foo 2 0: incorrect return" +[[ $bar = EXIT ]] || err_exit "foo 2 0: bar exit trap not set" +funcheck 2 0 +foo 2 3 +ret=$? +if (( $ret != 3 )) +then err_exit "foo 2 3: return is $ret not 3" +fi +[[ $bar = EXIT ]] || err_exit "foo 2 3: bar exit trap not set" +funcheck 2 3 +(foo 3 3) +ret=$? +if (( $ret != 3 )) +then err_exit "foo 3 3: return is $ret not 3" +fi +foo=EXIT +funcheck 3 3 +cat > $file <<! +return 3 +exit 4 +! +( . $file ) +ret=$? +if (( $ret != 3 )) +then err_exit "return in dot script is $ret should be 3" +fi +chmod 755 $file +( $file ) +ret=$? +if (( $ret != 3 )) +then err_exit "return in script is $ret should be 3" +fi +cat > $file <<! +: line 1 +# next line should fail and cause an exit +: > / +exit 4 +! +( . $file ; exit 5 ) 2> /dev/null +ret=$? +if (( $ret != 1 )) +then err_exit "error in dot script is $ret should be 1" +fi +( $file; exit 5 ) 2> /dev/null +ret=$? +if (( $ret != 5 )) +then err_exit "error in script is $ret should be 5" +fi +cat > $file <<\! +print -r -- "$0" +! +x=$( . $file) +if [[ $x != $0 ]] +then err_exit "\$0 in a dot script is $x. Should be $0" +fi +x=$($SHELL -i 2> /dev/null <<\! +typeset -i x=1/0 +print hello +! +) +if [[ $x != hello ]] +then err_exit "interactive shell terminates with error in bltin" +fi +x=$( set -e + false + print bad + ) +if [[ $x != '' ]] +then err_exit "set -e doesn't terminate script on error" +fi +x=$( set -e + trap 'exit 0' EXIT + false + print bad + ) +if (( $? != 0 )) +then err_exit "exit 0 in trap should doesn't set exit value to 0" +fi +$SHELL <<\! +trap 'exit 8' EXIT +exit 1 +! +if (( $? != 8 )) +then err_exit "exit 8 in trap should set exit value to 8" +fi +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/select.sh b/usr/src/lib/libshell/common/tests/select.sh new file mode 100644 index 0000000000..aec1903fb7 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/select.sh @@ -0,0 +1,63 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +trap "rm -f /tmp/Sh$$*" EXIT +PS3='ABC ' + +cat > /tmp/Sh$$.1 <<\! +1) foo +2) bar +3) bam +! + +select i in foo bar bam +do case $i in + foo) break;; + *) err_exit "select 1 not working" + break;; + esac +done 2> /dev/null <<! +1 +! + +unset i +select i in foo bar bam +do case $i in + foo) err_exit "select foo not working" 2>&3 + break;; + *) if [[ $REPLY != foo ]] + then err_exit "select REPLY not correct" 2>&3 + fi + ( set -u; : $i ) || err_exit "select: i not set to null" 2>&3 + break;; + esac +done 3>&2 2> /tmp/Sh$$.2 <<! +foo +! +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/shtests b/usr/src/lib/libshell/common/tests/shtests new file mode 100644 index 0000000000..a094d8ed20 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/shtests @@ -0,0 +1,63 @@ +# This program runs ksh regression tests +# shtests [ name=value ... ] a.sh b.sh ... + +unset DISPLAY ENV FIGNORE +LANG=C +LC_ALL=C +time=1 +while : +do case $1 in + *=*) n=${1%%=*} + v=${1#*=} + eval $n=\'$v\' + export $n + ;; + -t|--t*)time= + ;; + *) break + ;; + esac + shift +done +export LANG LC_ALL PATH PWD SHELL +PWD=`pwd` +SHELL=${SHELL-ksh} +case $0 in +/*) d=`dirname $0`;; +*/*) d=$PWD/`dirname $0`;; +*) d=$PWD;; +esac +case $SHELL in +/*) ;; +*/*) SHELL=$d/$SHELL;; +*) SHELL=$(whence $SHELL);; +esac +PATH=/bin:/usr/bin +if [[ -d /usr/ucb ]] +then PATH=$PATH:/usr/ucb +fi +PATH=$PATH:$d +if [[ $INSTALLROOT && -r $INSTALLROOT/bin/.paths ]] +then PATH=$INSTALLROOT/bin:$PATH +fi +for i in ${*-*.sh} +do echo test $i begins ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} + t=$(grep -c err_exit $i) + if (( $t )) + then (( t = $t - 1 )) + fi + T=test + if (( $t != 1 )) + then T=${T}s + fi + E=error + if $SHELL $i + then echo test $i passed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} "[ $t $T 0 ${E}s ]" + else e=$? + E=error + if (( $e != 1 )) + then E=${E}s + fi + echo test $i failed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T $e $E ]" + fi +done diff --git a/usr/src/lib/libshell/common/tests/substring.sh b/usr/src/lib/libshell/common/tests/substring.sh new file mode 100644 index 0000000000..2859d65671 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/substring.sh @@ -0,0 +1,504 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 j=4 +base=/home/dgk/foo//bar +string1=$base/abcabcabc +if [[ ${string1:0} != "$string1" ]] +then err_exit "string1:0" +fi +if [[ ${string1: -1} != "c" ]] +then err_exit "string1: -1" +fi +if [[ ${string1:0:1000} != "$string1" ]] +then err_exit "string1:0" +fi +if [[ ${string1:1} != "${string1#?}" ]] +then err_exit "string1:1" +fi +if [[ ${string1:1:4} != home ]] +then err_exit "string1:1:4" +fi +if [[ ${string1: -5:4} != bcab ]] +then err_exit "string1: -5:4" +fi +if [[ ${string1:1:j} != home ]] +then err_exit "string1:1:j" +fi +if [[ ${string1:(j?1:0):j} != home ]] +then err_exit "string1:(j?1:0):j" +fi +if [[ ${string1%*zzz*} != "$string1" ]] +then err_exit "string1%*zzz*" +fi +if [[ ${string1%%*zzz*} != "$string1" ]] +then err_exit "string1%%*zzz*" +fi +if [[ ${string1#*zzz*} != "$string1" ]] +then err_exit "string1#*zzz*" +fi +if [[ ${string1##*zzz*} != "$string1" ]] +then err_exit "string1##*zzz*" +fi +if [[ ${string1%+(abc)} != "$base/abcabc" ]] +then err_exit "string1%+(abc)" +fi +if [[ ${string1%%+(abc)} != "$base/" ]] +then err_exit "string1%%+(abc)" +fi +if [[ ${string1%/*} != "$base" ]] +then err_exit "string1%/*" +fi +if [[ "${string1%/*}" != "$base" ]] +then err_exit '"string1%/*"' +fi +if [[ ${string1%"/*"} != "$string1" ]] +then err_exit 'string1%"/*"' +fi +if [[ ${string1%%/*} != "" ]] +then err_exit "string1%%/*" +fi +if [[ ${string1#*/bar} != /abcabcabc ]] +then err_exit "string1#*bar" +fi +if [[ ${string1##*/bar} != /abcabcabc ]] +then err_exit "string1#*bar" +fi +if [[ "${string1#@(*/bar|*/foo)}" != //bar/abcabcabc ]] +then err_exit "string1#@(*/bar|*/foo)" +fi +if [[ ${string1##@(*/bar|*/foo)} != /abcabcabc ]] +then err_exit "string1##@(*/bar|*/foo)" +fi +if [[ ${string1##*/@(bar|foo)} != /abcabcabc ]] +then err_exit "string1##*/@(bar|foo)" +fi +foo=abc +if [[ ${foo#a[b*} != abc ]] +then err_exit "abc#a[b*} != abc" +fi +if [[ ${foo//[0-9]/bar} != abc ]] +then err_exit '${foo//[0-9]/bar} not expanding correctly' +fi +foo='(abc)' +if [[ ${foo#'('} != 'abc)' ]] +then err_exit "(abc)#( != abc)" +fi +if [[ ${foo%')'} != '(abc' ]] +then err_exit "(abc)%) != (abc" +fi +foo=a123b456c +if [[ ${foo/[0-9]?/""} != a3b456c ]] +then err_exit '${foo/[0-9]?/""} not expanding correctly' +fi +if [[ ${foo//[0-9]/""} != abc ]] +then err_exit '${foo//[0-9]/""} not expanding correctly' +fi +if [[ ${foo/#a/b} != b123b456c ]] +then err_exit '${foo/#a/b} not expanding correctly' +fi +if [[ ${foo/#?/b} != b123b456c ]] +then err_exit '${foo/#?/b} not expanding correctly' +fi +if [[ ${foo/%c/b} != a123b456b ]] +then err_exit '${foo/%c/b} not expanding correctly' +fi +if [[ ${foo/%?/b} != a123b456b ]] +then err_exit '${foo/%?/b} not expanding correctly' +fi +while read -r pattern string expected +do if (( expected )) + then if [[ $string != $pattern ]] + then err_exit "$pattern does not match $string" + fi + if [[ ${string##$pattern} != "" ]] + then err_exit "\${$string##$pattern} not null" + fi + if [ "${string##$pattern}" != '' ] + then err_exit "\"\${$string##$pattern}\" not null" + fi + if [[ ${string/$pattern} != "" ]] + then err_exit "\${$string/$pattern} not null" + fi + else if [[ $string == $pattern ]] + then err_exit "$pattern matches $string" + fi + fi +done <<- \EOF + +(a)*+(a) aabca 1 + !(*.o) foo.o 0 + !(*.o) foo.c 1 +EOF +xx=a/b/c/d/e +yy=${xx#*/} +if [[ $yy != b/c/d/e ]] +then err_exit '${xx#*/} != a/b/c/d/e when xx=a/b/c/d/e' +fi +if [[ ${xx//\//\\} != 'a\b\c\d\e' ]] +then err_exit '${xx//\//\\} not working' +fi +x=[123]def +if [[ "${x//\[(*)\]/\{\1\}}" != {123}def ]] +then err_exit 'closing brace escape not working' +fi +unset foo +foo=one/two/three +if [[ ${foo//'/'/_} != one_two_three ]] +then err_exit 'single quoting / in replacements failed' +fi +if [[ ${foo//"/"/_} != one_two_three ]] +then err_exit 'double quoting / in replacements failed' +fi +if [[ ${foo//\//_} != one_two_three ]] +then err_exit 'escaping / in replacements failed' +fi +function myexport +{ + nameref var=$1 + if (( $# > 1 )) + then export $1=$2 + fi + if (( $# > 2 )) + then print $(myexport "$1" "$3" ) + return + fi + typeset val + val=$(export | grep "^$1=") + print ${val#"$1="} + +} +export dgk=base +if [[ $(myexport dgk fun) != fun ]] +then err_exit 'export inside function not working' +fi +val=$(export | grep "^dgk=") +if [[ ${val#dgk=} != base ]] +then err_exit 'export not restored after function call' +fi +if [[ $(myexport dgk fun fun2) != fun2 ]] +then err_exit 'export inside function not working with recursive function' +fi +val=$(export | grep "^dgk=") +if [[ ${val#dgk=} != base ]] +then err_exit 'export not restored after recursive function call' +fi +if [[ $(dgk=try3 myexport dgk) != try3 ]] +then err_exit 'name=value not added to export list with function call' +fi +val=$(export | grep "^dgk=") +if [[ ${val#dgk=} != base ]] +then err_exit 'export not restored name=value function call' +fi +unset zzz +if [[ $(myexport zzz fun) != fun ]] +then err_exit 'export inside function not working for zzz' +fi +if [[ $(export | grep "zzz=") ]] +then err_exit 'zzz exported after function call' +fi +set -- foo/bar bam/yes last/file/done +if [[ ${@/*\/@(*)/${.sh.match[1]}} != 'bar yes done' ]] +then err_exit '.sh.match not working with $@' +fi +if [[ ${@/*\/@(*)/\1} != 'bar yes done' ]] +then err_exit '\1 not working with $@' +fi +var=(foo/bar bam/yes last/file/done) +if [[ ${var[@]/*\/@(*)/${.sh.match[1]}} != 'bar yes done' ]] +then err_exit '.sh.match not working with ${var[@]}' +fi +if [[ ${var[@]/*\/@(*)/\1} != 'bar yes done' ]] +then err_exit '\1 not working with ${var[@]}' +fi +var='abc_d2ef.462abc %%' +if [[ ${var/+(\w)/Q} != 'Q.462abc %%' ]] +then err_exit '${var/+(\w)/Q} not workding' +fi +if [[ ${var//+(\w)/Q} != 'Q.Q %%' ]] +then err_exit '${var//+(\w)/Q} not workding' +fi +if [[ ${var//+(\S)/Q} != 'Q Q' ]] +then err_exit '${var//+(\S)/Q} not workding' +fi +if [[ "$(LC_ALL=debug $SHELL <<- \+EOF+ + x=a<2bc><3xyz>g + print ${#x} + +EOF+)" != 4 + ]] +then err_exit '${#x} not working with multibyte locales' +fi +foo='foo+bar+' +[[ $(print -r -- ${foo//+/'|'}) != 'foo|bar|' ]] && err_exit "\${foobar//+/'|'}" +[[ $(print -r -- ${foo//+/"|"}) != 'foo|bar|' ]] && err_exit '${foobar//+/"|"}' +[[ $(print -r -- "${foo//+/'|'}") != 'foo|bar|' ]] && err_exit '"${foobar//+/'"'|'"'}"' +[[ $(print -r -- "${foo//+/"|"}") != 'foo|bar|' ]] && err_exit '"${foobar//+/"|"}"' +unset x +x=abcedfg +: ${x%@(d)f@(g)} +[[ ${.sh.match[0]} == dfg ]] || err_exit '.sh.match[0] not dfg' +[[ ${.sh.match[1]} == d ]] || err_exit '.sh.match[1] not d' +[[ ${.sh.match[2]} == g ]] || err_exit '.sh.match[2] not g' +x=abcedddfg +: ${x%%+(d)f@(g)} +[[ ${.sh.match[1]} == ddd ]] || err_exit '.sh.match[1] not ddd' +unset a b +a='\[abc @(*) def\]' +b='[abc 123 def]' +[[ ${b//$a/\1} == 123 ]] || err_exit "\${var/pattern} not working with \[ in pattern" +unset X +$SHELL -c '[[ ! ${X[@]:0:300} ]]' 2> /dev/null || err_exit '${X[@]:0:300} with X undefined fails' +$SHELL -c '[[ ${@:0:300} == "$0" ]]' 2> /dev/null || err_exit '${@:0:300} with no arguments fails' +i=20030704 +[[ ${i#{6}(?)} == 04 ]] || err_exit '${i#{6}(?)} not working' +[[ ${i#{6,6}(?)} == 04 ]] || err_exit '${i#{6,6}(?)} not working' +LC_ALL=posix +i=" ." +[[ $(printf "<%s>\n" ${i#' '}) == '<.>' ]] || err_exit 'printf "<%s>\n" ${i#' '} failed' +unset x +x=foo +[[ "${x%o}(1)" == "fo(1)" ]] || err_exit 'print ${}() treated as pattern' +unset i pattern string +string=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz +integer i +for((i=0; i < ${#string}; i++)) +do pattern+='@(?)' +done +[[ $(string=$string $SHELL -c ": \${string/$pattern/}; print \${.sh.match[26]}") == Z ]] || err_exit -u2 'sh.match[26] not Z' +: ${string/$pattern/} +(( ${#.sh.match[@]} == 53 )) || err_exit '.sh.match has wrong number of elements' +[[ ${.sh.match[@]:2:4} == 'B C D E' ]] || err_exit '${.sh.match[@]:2:4} incorrect' + +D=$';' E=$'\\\\' Q=$'"' S=$'\'' M='nested pattern substitution failed' + +x='-(-)-' +[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M +x='-(-)-)-' +[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M +x='-(-()-)-' +[[ ${x/*%(())*/\1} == '()' ]] || err_exit $M +x='-(-\)-)-' +[[ ${x/*%(())*/\1} == '(-\)' ]] || err_exit $M +x='-(-\\)-)-' +[[ ${x/*%(())*/\1} == '(-\\)' ]] || err_exit $M +x='-(-(-)-' +[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M +x='-(-(-)-)-' +[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M +x='-(-[-]-)-' +[[ ${x/*%(()[])*/\1} == '(-[-]-)' ]] || err_exit $M +x='-[-(-)-]-' +[[ ${x/*%(()[])*/\1} == '(-)' ]] || err_exit $M +x='-(-[-)-]-' +[[ ${x/*%(()[])*/\1} == '-(-[-)-]-' ]] || err_exit $M +x='-(-[-]-)-' +[[ ${x/*%([]())*/\1} == '[-]' ]] || err_exit $M +x='-[-(-)-]-' +[[ ${x/*%([]())*/\1} == '[-(-)-]' ]] || err_exit $M +x='-(-[-)-]-' +[[ ${x/*%([]())*/\1} == '-(-[-)-]-' ]] || err_exit $M + +x='-((-))-' +[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M +x='-((-))-' +[[ ${x/~(-g)*%(())*/\1} == '((-))-' ]] || err_exit $M +x='-((-))-' +[[ ${x/~(-g:*)*%(())*/\1} == '(-)' ]] || err_exit $M +x='-((-))-' +[[ ${x/~(+g)*%(())*/\1} == '(-)' ]] || err_exit $M +x='-((-))-' +[[ ${x/~(+g:*)*%(())*/\1} == '(-)' ]] || err_exit $M +x='-((-))-' +[[ ${x/*(?)*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M +x='-((-))-' +[[ ${x/~(-g)*(?)*%(())*(?)*/:\1:\2:\3:} == '::((-))::-' ]] || err_exit $M +x='-((-))-' +[[ ${x/~(-g:*(?))*%(())*(?)*/:\1:\2:\3:} == '::(-):)-:' ]] || err_exit $M +x='-((-))-' +[[ ${x/~(+g)*(?)*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M +x='-((-))-' +[[ ${x/~(+g:*(?))*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M +x='call(a+b,x/(c/d),(0));' +[[ ${x/+([[:alnum:]])*([[:space:]])(*%(()))*/:\1:\2:\3:} == ':call::(a+b,x/(c/d),(0)):' ]] || err_exit $M + +x='-(-;-)-' +[[ ${x/*%(()D${D})*/\1} == '-(-;-)-' ]] || err_exit $M +x='-(-);-' +[[ ${x/*%(()D${D})*/\1} == '(-)' ]] || err_exit $M +x='-(-)\;-' +[[ ${x/*%(()D${D})*/\1} == '(-)' ]] || err_exit $M +x='-(-\;-)-' +[[ ${x/*%(()D${D}E${E})*/\1} == '(-\;-)' ]] || err_exit $M +x='-(-)\;-' +[[ ${x/*%(()D${D}E${E})*/\1} == '(-)' ]] || err_exit $M +x='-(-(-)\;-)-' +[[ ${x/*%(()D${D}E${E})*/\1} == '(-)' ]] || err_exit $M + +x='-(-")"-)-' +[[ ${x/*%(()Q${Q})*/\1} == '(-")"-)' ]] || err_exit $M +x='-(-\")"-)-' +[[ ${x/*%(()Q${Q})*/\1} == '(-\")"-)' ]] || err_exit $M +x='-(-\")\"-)-' +[[ ${x/*%(()Q${Q})*/\1} == '(-\")\"-)' ]] || err_exit $M +x=$'-(-\\\'")\\\'-)-' +[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\\'")\\\'-)' ]] || err_exit $M +x=$'-(-\\\'")"-)-' +[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M +x=$'-(-\\\'")"\'-)-' +[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M +x=$'-(-\\"\')\'\\"-)-' +[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M +x=$'-(-\')\\\'\'-)-' +[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M +x=$'-(-\'")\'-)-' +[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\'")\'-)' ]] || err_exit $M +x=$'-(-\\\'")"-)-' +[[ ${x/*%(()L${S}Q${Q})*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M +x=$'-(-\\\'")"\'-)-' +[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M +x=$'-(-\\"\')\'\\"-)-' +[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M +x=$'-(-\')\\\'\'-)-' +[[ ${x/*%(()L${S}Q${Q})*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M +x='-(-")"-)-' +[[ ${x/*%(()Q${Q})*/\1} == '(-")"-)' ]] || err_exit $M +x='-(-\")"-)-' +[[ ${x/*%(()Q${Q})*/\1} == '(-\")"-)' ]] || err_exit $M +x='-(-\")\"-)-' +[[ ${x/*%(()Q${Q})*/\1} == '(-\")\"-)' ]] || err_exit $M + +x='-(-\)-)-' +[[ ${x/*%(()E${E})*/\1} == '(-\)-)' ]] || err_exit $M +x='-(-\\)-)-' +[[ ${x/*%(()E${E})*/\1} == '(-\\)' ]] || err_exit $M +x='-(-\")"-)-' +[[ ${x/*%(()E${E}Q${Q})*/\1} == '(-\")' ]] || err_exit $M +x='-(-\")\"-)-' +[[ ${x/*%(()E${E}Q${Q})*/\1} == '(-\")' ]] || err_exit $M +x=$'-(-\'")"-)-' +[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'-(-\'")"-)-' ]] || err_exit $M +x=$'-(-\\\'")"-)-' +[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'(-\\\'")"-)' ]] || err_exit $M +x=$'-(-\\"\')\'\\"-)-' +[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M +x=$'-(-\\\'")"-)-' +[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\\'")"-)' ]] || err_exit $M +x=$'-(-\\"\')\'\\"-)-' +[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M +x=$'-(-\\"\')\\\'\\"-)-' +[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\"\')\\\'\\"-)' ]] || err_exit $M +x=$'-(-\\"\')\\\'\\"\'-)-' +[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'-(-\\"\')\\\'\\"\'-)-' ]] || err_exit $M + +x='-(-;-)-' +[[ ${x/*%(()D\;)*/\1} == '-(-;-)-' ]] || err_exit $M +x='-(-);-' +[[ ${x/*%(()D\;)*/\1} == '(-)' ]] || err_exit $M +x='-(-)\;-' +[[ ${x/*%(()D\;)*/\1} == '(-)' ]] || err_exit $M +x='-(-\;-)-' +[[ ${x/*%(()D\;E\\)*/\1} == '(-\;-)' ]] || err_exit $M +x='-(-);-' +[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M +x='-(-)\;-' +[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M +x='-(-(-)\;-)-' +[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M + +x='-(-")"-)-' +[[ ${x/*%(()Q\")*/\1} == '(-")"-)' ]] || err_exit $M +x='-(-\")"-)-' +[[ ${x/*%(()Q\")*/\1} == '(-\")"-)' ]] || err_exit $M +x='-(-\")\"-)-' +[[ ${x/*%(()Q\")*/\1} == '(-\")\"-)' ]] || err_exit $M +x=$'-(-\\\'")\\\'-)-' +[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\\'")\\\'-)' ]] || err_exit $M +x=$'-(-\\\'")"-)-' +[[ ${x/*%(()Q\'Q\")*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M +x=$'-(-\\\'")"\'-)-' +[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M +x=$'-(-\\"\')\'\\"-)-' +[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M +x=$'-(-\')\\\'\'-)-' +[[ ${x/*%(()Q\'Q\")*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M +x=$'-(-\'")\'-)-' +[[ ${x/*%(()L\'Q\")*/\1} == $'(-\'")\'-)' ]] || err_exit $M +x=$'-(-\\\'")"-)-' +[[ ${x/*%(()L\'Q\")*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M +x=$'-(-\\\'")"\'-)-' +[[ ${x/*%(()L\'Q\")*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M +x=$'-(-\\"\')\'\\"-)-' +[[ ${x/*%(()L\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M +x=$'-(-\')\\\'\'-)-' +[[ ${x/*%(()L\'Q\")*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M +x='-(-")"-)-' +[[ ${x/*%(()Q\")*/\1} == '(-")"-)' ]] || err_exit $M +x='-(-\")"-)-' +[[ ${x/*%(()Q\")*/\1} == '(-\")"-)' ]] || err_exit $M +x='-(-\")\"-)-' +[[ ${x/*%(()Q\")*/\1} == '(-\")\"-)' ]] || err_exit $M + +x='-(-\)-)-' +[[ ${x/*%(()E\\)*/\1} == '(-\)-)' ]] || err_exit $M +x='-(-\\)-)-' +[[ ${x/*%(()E\\)*/\1} == '(-\\)' ]] || err_exit $M +x='-(-\")"-)-' +[[ ${x/*%(()E\\Q\")*/\1} == '(-\")' ]] || err_exit $M +x='-(-\")\"-)-' +[[ ${x/*%(()E\\Q\")*/\1} == '(-\")' ]] || err_exit $M +x=$'-(-\'")"-)-' +[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'-(-\'")"-)-' ]] || err_exit $M +x=$'-(-\\\'")"-)-' +[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'(-\\\'")"-)' ]] || err_exit $M +x=$'-(-\\"\')\'\\"-)-' +[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M +x=$'-(-\\\'")"-)-' +[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\\'")"-)' ]] || err_exit $M +x=$'-(-\\"\')\'\\"-)-' +[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M +x=$'-(-\\"\')\\\'\\"-)-' +[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\"\')\\\'\\"-)' ]] || err_exit $M +x=$'-(-\\"\')\\\'\\"\'-)-' +[[ ${x/*%(()E\\L\'Q\")*/\1} == $'-(-\\"\')\\\'\\"\'-)-' ]] || err_exit $M + +pattern=00 +var=100 +[[ $( print $(( ${var%%00} )) ) == 1 ]] || err_exit "arithmetic with embeddded patterns fails" +[[ $( print $(( ${var%%$pattern} )) ) == 1 ]] || err_exit "arithmetic with embeddded pattern variables fails" +if [[ ax == @(a)* ]] && [[ ${.sh.match[1]:0:${#.sh.match[1]}} != a ]] +then err_exit '${.sh.match[1]:1:${#.sh.match[1]}} not expanding correctly' +fi + +string='foo(d:\nt\box\something)bar' +expected='d:\nt\box\something' +[[ ${string/*\(+([!\)])\)*/\1} == "$expected" ]] || err_exit "substring expansion failed '${string/*\(+([!\)])\)*/\1}' returned -- '$expected' expected" +if [[ $($SHELL -c $'export LC_ALL=en_US.UTF-8; print -r "\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254" | wc -m' 2>/dev/null) == 10 ]] +then LC_ALL=en_US.UTF-8 $SHELL -c b1=$'"\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254"; [[ ${b1:4:1} == w ]]' || err_exit 'Multibyte ${var:offset:len} not working correctly' +fi +{ $SHELL -c 'unset x;[[ ${SHELL:$x} == $SHELL ]]';} 2> /dev/null || err_exit '${var:$x} fails when x is not set' +{ $SHELL -c 'x=;[[ ${SHELL:$x} == $SHELL ]]';} 2> /dev/null || err_exit '${var:$x} fails when x is null' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_getconf.sh b/usr/src/lib/libshell/common/tests/sun_solaris_getconf.sh new file mode 100644 index 0000000000..a8eaeb75f6 --- /dev/null +++ b/usr/src/lib/libshell/common/tests/sun_solaris_getconf.sh @@ -0,0 +1,160 @@ +#!/bin/ksh93 + +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# sun_solaris_getconf.sh - test the ksh93 getconf builtin for compatibility +# with /usr/bin/getconf +# + +# test setup +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 + + +# setup +integer mismatch # counts mismatches between builtin and external command +integer getconf_keys # counts tests (paranoid check to make sure the test loop works) +export PATH=/usr/bin:/bin + +# prechecks +[ ! -f "/bin/getconf" ] && err_exit '/bin/getconf not found.' +[ ! -x "/bin/getconf" ] && err_exit '/bin/getconf not executable.' + +# compare builtin getconf output with /usr/bin/getconf +function compare_normal +{ + mismach=0 getconf_keys=0 + /usr/bin/getconf -a | + while read i ; do + let getconf_keys++ + t="${i%:*}" + + a="$(getconf "$t" 2>/dev/null)" + b="$(/usr/bin/getconf "$t" 2>/dev/null)" + + if [ "$a" != "$b" ] ; then + print -u2 "getconf/normal built mismatch: |$t|:|$a| != |$b|" + let mismatch++ + fi + done +} + +# compare builtin getconf output with /usr/bin/getconf while passing a path argument +function compare_path +{ + mismach=0 getconf_keys=0 + /usr/bin/getconf -a | + while read i ; do + let getconf_keys++ + t="${i%:*}" + + a="$(getconf "$t" "/tmp" 2>/dev/null)" + b="$(/usr/bin/getconf "$t" "/tmp" 2>/dev/null)" + + if [ "$a" != "$b" ] ; then + print -u2 "getconf/path built mismatch: |$t|:|$a| != |$b|" + let mismatch++ + fi + done +} + +# future versions of this test should test the following ${PATH}s, too: +# "/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin" \ +#"/usr/xpg4/bin:/bin:/usr/bin" \ +for i in \ + "/bin:/usr/bin" +do + export PATH="${i}" + + ## test whether the getconf builtin is available + if [ "$(builtin | fgrep "/bin/getconf")" = "" ] ; then + err_exit '/bin/getconf not found in the list of builtins.' + fi + + + ## compare "getconf -a" output + if [ "$(getconf -a)" != "$(/usr/bin/getconf -a)" ] ; then + err_exit 'getconf -a output mismatch.' + fi + + + ## check for a key which is only supported by the AST builtin version of getconf: + if [ "$(getconf LIBPREFIX)" != "lib" ] ; then + err_exit 'getconf LIBPREFIX did not return "lib".' + fi + + + ## run normal test + compare_normal + [ ${getconf_keys} -eq 0 ] && err_exit "getconf/normal not working (PATH=${PATH})." + [ ${mismatch} -gt 0 ] && err_exit "getconf/normal test found ${mismatch} differences (PATH=${PATH})." + + # run the same test in a seperate shell + # (we explicitly test this because ast-ksh.2007-01-11 picks up /usr/xpg6/bin/getconf + # if /usr/xpg6/bin/ comes in ${PATH} before /usr/bin (this happens only of ${PATH} + # contains /usr/xpg6/bin before ksh93 is started)). + ${SHELL} -c "integer mismatch ; \ + integer getconf_keys ; \ + $(functions) ; \ + compare_normal ; + [ \${getconf_keys} -eq 0 ] && err_exit \"getconf/normal not working (PATH=\${PATH}).\" ; \ + [ \${mismatch} -gt 0 ] && err_exit \"getconf/normal test found \${mismatch} differences (PATH=\${PATH}).\" ; \ + exit $((Errors))" + let Errors+=$? + + + ## run test with path argument + compare_path + [ ${getconf_keys} -eq 0 ] && err_exit "getconf/path not working." + [ ${mismatch} -gt 0 ] && err_exit "getconf/path test found ${mismatch} differences." + + # run the same test in a seperate shell + # (see comment above) + ${SHELL} -c "integer mismatch ; \ + integer getconf_keys ; \ + $(functions) ; \ + compare_path ; + [ \${getconf_keys} -eq 0 ] && err_exit \"getconf/normal not working (PATH=\${PATH}).\" ; \ + [ \${mismatch} -gt 0 ] && err_exit \"getconf/normal test found \${mismatch} differences (PATH=\${PATH}).\" ; \ + exit $((Errors))" + let Errors+=$? +done + +# test done +exit $((Errors)) + diff --git a/usr/src/lib/libshell/common/tests/tilde.sh b/usr/src/lib/libshell/common/tests/tilde.sh new file mode 100644 index 0000000000..6ebfd8504c --- /dev/null +++ b/usr/src/lib/libshell/common/tests/tilde.sh @@ -0,0 +1,87 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r $Command: "$@" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +function home # id +{ + typeset IFS=: pwd=/etc/passwd + set -o noglob + if [[ -f $pwd ]] && grep -c "^$1:" $pwd > /dev/null + then set -- $(grep "^$1:" $pwd) + print -r -- "$6" + else print . + fi +} + +Command=${0##*/} +integer Errors=0 +OLDPWD=/bin +if [[ ~ != $HOME ]] +then err_exit '~' not $HOME +fi +x=~ +if [[ $x != $HOME ]] +then err_exit x=~ not $HOME +fi +x=x:~ +if [[ $x != x:$HOME ]] +then err_exit x=x:~ not x:$HOME +fi +if [[ ~+ != $PWD ]] +then err_exit '~' not $PWD +fi +x=~+ +if [[ $x != $PWD ]] +then err_exit x=~+ not $PWD +fi +if [[ ~- != $OLDPWD ]] +then err_exit '~' not $PWD +fi +x=~- +if [[ $x != $OLDPWD ]] +then err_exit x=~- not $OLDPWD +fi +for u in root Administrator +do h=$(home $u) + if [[ $h != . ]] + then [[ ~$u -ef $h ]] || err_exit "~$u not $h" + x=~$u + [[ $x -ef $h ]] || "x=~$u not $h" + break + fi +done +x=~%% +if [[ $x != '~%%' ]] +then err_exit 'x='~%%' not '~%% +fi +x=~:~ +if [[ $x != "$HOME:$HOME" ]] +then err_exit x=~:~ not $HOME:$HOME +fi +HOME=/ +[[ ~ == / ]] || err_exit '~ should be /' +[[ ~/foo == /foo ]] || err_exit '~/foo should be /foo when ~==/' +exit $((Errors)) diff --git a/usr/src/lib/libshell/common/tests/variables.sh b/usr/src/lib/libshell/common/tests/variables.sh new file mode 100644 index 0000000000..bc499c890c --- /dev/null +++ b/usr/src/lib/libshell/common/tests/variables.sh @@ -0,0 +1,558 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1982-2007 AT&T Knowledge Ventures # +# and is licensed under the # +# Common Public License, Version 1.0 # +# by AT&T Knowledge Ventures # +# # +# A copy of the License is available at # +# http://www.opensource.org/licenses/cpl1.0.txt # +# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# David Korn <dgk@research.att.com> # +# # +######################################################################## +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + let Errors+=1 +} +alias err_exit='err_exit $LINENO' + +Command=${0##*/} +integer Errors=0 +# RANDOM +if (( RANDOM==RANDOM || $RANDOM==$RANDOM )) +then err_exit RANDOM variable not working +fi +# SECONDS +sleep 3 +if (( SECONDS < 2 )) +then err_exit SECONDS variable not working +fi +# _ +set abc def +if [[ $_ != def ]] +then err_exit _ variable not working +fi +# ERRNO +#set abc def +#rm -f foobar# +#ERRNO= +#2> /dev/null < foobar# +#if (( ERRNO == 0 )) +#then err_exit ERRNO variable not working +#fi +# PWD +if [[ ! $PWD -ef . ]] +then err_exit PWD variable not working +fi +# PPID +if [[ $($SHELL -c 'print $PPID') != $$ ]] +then err_exit PPID variable not working +fi +# OLDPWD +old=$PWD +cd / +if [[ $OLDPWD != $old ]] +then err_exit OLDPWD variable not working +fi +cd $old || err_exit cd failed +# REPLY +read <<-! + foobar + ! +if [[ $REPLY != foobar ]] +then err_exit REPLY variable not working +fi +integer save=$LINENO +# LINENO +LINENO=10 +# +# These lines intentionally left blank +# +if (( LINENO != 13)) +then err_exit LINENO variable not working +fi +LINENO=save+10 +IFS=: +x=a::b::c +if [[ $x != a::b::c ]] +then err_exit "Word splitting on constants" +fi +set -- $x +if [[ $# != 5 ]] +then err_exit ":: doesn't separate null arguments " +fi +set x +if x$1=0 2> /dev/null +then err_exit "x\$1=value treated as an assignment" +fi +# check for attributes across subshells +typeset -i x=3 +y=1/0 +if ( typeset x=y) 2> /dev/null +then print -u2 "attributes not passed to subshells" +fi +unset x +function x.set +{ + nameref foo=${.sh.name}.save + foo=${.sh.value} + .sh.value=$0 +} +x=bar +if [[ $x != x.set ]] +then err_exit 'x.set does not override assignment' +fi +x.get() +{ + nameref foo=${.sh.name}.save + .sh.value=$foo +} + +if [[ $x != bar ]] +then err_exit 'x.get does not work correctly' +fi +typeset +n foo +unset foo +foo=bar +( + unset foo + set +u + if [[ $foo != '' ]] + then err_exit '$foo not null after unset in subsehll' + fi +) +if [[ $foo != bar ]] +then err_exit 'unset foo in subshell produces side effect ' +fi +unset foo +if [[ $( { : ${foo?hi there} ; } 2>&1) != *'hi there' ]] +then err_exit '${foo?hi there} with foo unset does not print hi there on 2' +fi +x=$0 +set foobar +if [[ ${@:0} != "$x foobar" ]] +then err_exit '${@:0} not expanding correctly' +fi +set -- +if [[ ${*:0:1} != "$0" ]] +then err_exit '${@:0} not expanding correctly' +fi +ACCESS=0 +function COUNT.set +{ + (( ACCESS++ )) +} +COUNT=0 +(( COUNT++ )) +if (( COUNT != 1 || ACCESS!=2 )) +then err_exit " set discipline failure COUNT=$COUNT ACCESS=$ACCESS" +fi +LANG=C > /dev/null 2>&1 +if [[ $LANG != C ]] +then err_exit "C locale not working" +fi +unset RANDOM +unset -n foo +foo=junk +function foo.get +{ + .sh.value=stuff + unset -f foo.get +} +if [[ $foo != stuff ]] +then err_exit "foo.get discipline not working" +fi +if [[ $foo != junk ]] +then err_exit "foo.get discipline not working after unset" +fi +# special variables +set -- 1 2 3 4 5 6 7 8 9 10 +sleep 1000 & +if [[ $(print -r -- ${#10}) != 2 ]] +then err_exit '${#10}, where ${10}=10 not working' +fi +for i in @ '*' ! '#' - '?' '$' +do false + eval foo='$'$i bar='$'{$i} + if [[ ${foo} != "${bar}" ]] + then err_exit "\$$i not equal to \${$i}" + fi + command eval bar='$'{$i%?} 2> /dev/null || err_exit "\${$i%?} gives syntax error" + if [[ $i != [@*] && ${foo%?} != "$bar" ]] + then err_exit "\${$i%?} not correct" + fi + command eval bar='$'{$i#?} 2> /dev/null || err_exit "\${$i#?} gives syntax error" + if [[ $i != [@*] && ${foo#?} != "$bar" ]] + then err_exit "\${$i#?} not correct" + fi + command eval foo='$'{$i} bar='$'{#$i} || err_exit "\${#$i} gives synta +x error" + if [[ $i != @([@*]) && ${#foo} != "$bar" ]] + then err_exit "\${#$i} not correct" + fi +done +kill $! +unset x +CDPATH=/ +x=$(cd tmp) +if [[ $x != /tmp ]] +then err_exit 'CDPATH does not display new directory' +fi +mkdir /tmp/ksh$$ +CDPATH=/: +x=$(cd /tmp;cd ksh$$) +if [[ $x ]] +then err_exit 'CDPATH displays new directory when not used' +fi +x=$(cd tmp/ksh$$) +if [[ $x != /tmp/ksh$$ ]] +then err_exit "CDPATH tmp/ksh$$ does not display new directory" +fi +cd / +rm -rf /tmp/ksh$$ +TMOUT=100 +(TMOUT=20) +if (( TMOUT !=100 )) +then err_exit 'setting TMOUT in subshell affects parent' +fi +unset y +function setdisc # var +{ + eval function $1.get' + { + .sh.value=good + } + ' +} +y=bad +setdisc y +if [[ $y != good ]] +then err_exit 'setdisc function not working' +fi +integer x=$LINENO +: $'\ +' +if (( LINENO != x+3 )) +then err_exit '\<newline> gets linenumber count wrong' +fi +set -- +set -- "${@-}" +if (( $# !=1 )) +then err_exit '"${@-}" not expanding to null string' +fi +for i in : % + / 3b '**' '***' '@@' '{' '[' '}' !! '*a' '@a' '$foo' +do (eval : \${"$i"} 2> /dev/null) && err_exit "\${$i} not an syntax error" +done +unset IFS +( IFS=' ' ; read -r a b c <<-! + x y z + ! + if [[ $b ]] + then err_exit 'IFS=" " not causing adjacent space to be null string' + fi +) +read -r a b c <<-! +x y z +! +if [[ $b != y ]] +then err_exit 'IFS not restored after subshell' +fi + +# The next part generates 3428 IFS set/read tests. + +unset IFS x +function split +{ + i=$1 s=$2 r=$3 + IFS=': ' + set -- $i + IFS=' ' + g="[$#]" + while : + do case $# in + 0) break ;; + esac + g="$g($1)" + shift + done + case "$g" in + "$s") ;; + *) err_exit "IFS=': '; set -- '$i'; expected '$s' got '$g'" ;; + esac + print "$i" | IFS=": " read arg rem; g="($arg)($rem)" + case "$g" in + "$r") ;; + *) err_exit "IFS=': '; read '$i'; expected '$r' got '$g'" ;; + esac +} +for str in \ + '-' \ + 'a' \ + '- -' \ + '- a' \ + 'a -' \ + 'a b' \ + '- - -' \ + '- - a' \ + '- a -' \ + '- a b' \ + 'a - -' \ + 'a - b' \ + 'a b -' \ + 'a b c' +do + IFS=' ' + set x $str + shift + case $# in + 0) continue ;; + esac + f1=$1 + case $f1 in + '-') f1='' ;; + esac + shift + case $# in + 0) for d0 in '' ' ' + do + for d1 in '' ' ' ':' ' :' ': ' ' : ' + do + case $f1$d1 in + '') split "$d0$f1$d1" "[0]" "()()" ;; + ' ') ;; + *) split "$d0$f1$d1" "[1]($f1)" "($f1)()" ;; + esac + done + done + continue + ;; + esac + f2=$1 + case $f2 in + '-') f2='' ;; + esac + shift + case $# in + 0) for d0 in '' ' ' + do + for d1 in ' ' ':' ' :' ': ' ' : ' + do + case ' ' in + $f1$d1|$d1$f2) continue ;; + esac + for d2 in '' ' ' ':' ' :' ': ' ' : ' + do + case $f2$d2 in + '') split "$d0$f1$d1$f2$d2" "[1]($f1)" "($f1)()" ;; + ' ') ;; + *) split "$d0$f1$d1$f2$d2" "[2]($f1)($f2)" "($f1)($f2)" ;; + esac + done + done + done + continue + ;; + esac + f3=$1 + case $f3 in + '-') f3='' ;; + esac + shift + case $# in + 0) for d0 in '' ' ' + do + for d1 in ':' ' :' ': ' ' : ' + do + case ' ' in + $f1$d1|$d1$f2) continue ;; + esac + for d2 in ' ' ':' ' :' ': ' ' : ' + do + case $f2$d2 in + ' ') continue ;; + esac + case ' ' in + $f2$d2|$d2$f3) continue ;; + esac + for d3 in '' ' ' ':' ' :' ': ' ' : ' + do + case $f3$d3 in + '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;; + ' ') ;; + *) x=$f2$d2$f3$d3 + x=${x#' '} + x=${x%' '} + split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)" + ;; + esac + done + done + done + done + continue + ;; + esac +done +unset IFS + +if [[ $( (print ${12345:?}) 2>&1) != *12345* ]] +then err_exit 'Incorrect error message with ${12345?}' +fi +unset foobar +if [[ $( (print ${foobar:?}) 2>&1) != *foobar* ]] +then err_exit 'Incorrect error message with ${foobar?}' +fi +unset bar +if [[ $( (print ${bar:?bam}) 2>&1) != *bar*bam* ]] +then err_exit 'Incorrect error message with ${foobar?}' +fi +{ $SHELL -c ' +function foo +{ + typeset SECONDS=0 + sleep 1.5 + print $SECONDS + +} +x=$(foo) +(( x >1 && x < 2 )) +' +} 2> /dev/null || err_exit 'SECONDS not working in function' +trap 'rm -f /tmp/script$$ /tmp/out$$' EXIT +cat > /tmp/script$$ <<-\! + posixfun() + { + unset x + nameref x=$1 + print -r -- "$x" + } + function fun + { + nameref x=$1 + print -r -- "$x" + } + if [[ $1 ]] + then file=${.sh.file} + else print -r -- "${.sh.file}" + fi +! +chmod +x /tmp/script$$ +. /tmp/script$$ 1 +[[ $file == /tmp/script$$ ]] || err_exit ".sh.file not working for dot scripts" +[[ $($SHELL /tmp/script$$) == /tmp/script$$ ]] || err_exit ".sh.file not working for scripts" +[[ $(posixfun .sh.file) == /tmp/script$$ ]] || err_exit ".sh.file not working for posix functions" +[[ $(fun .sh.file) == /tmp/script$$ ]] || err_exit ".sh.file not working for functions" +[[ $(posixfun .sh.fun) == posixfun ]] || err_exit ".sh.fun not working for posix functions" +[[ $(fun .sh.fun) == fun ]] || err_exit ".sh.fun not working for functions" +[[ $(posixfun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for posix functions" +[[ $(fun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for functions" +( + [[ $(posixfun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for posix functions in subshells" + [[ $(fun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for functions in subshells" + (( .sh.subshell == 1 )) || err_exit ".sh.subshell not working in a subshell" +) +TIMEFORMAT='this is a test' +[[ $({ { time :;} 2>&1;}) == "$TIMEFORMAT" ]] || err_exit 'TIMEFORMAT not working' +: ${.sh.version} +[[ $(alias integer) == *.sh.* ]] && err_exit '.sh. prefixed to alias name' +: ${.sh.version} +[[ $(whence rm) == *.sh.* ]] && err_exit '.sh. prefixed to tracked alias name' +: ${.sh.version} +[[ $(cd /bin;env | grep PWD) == *.sh.* ]] && err_exit '.sh. prefixed to PWD' +# unset discipline bug fix +dave=dave +function dave.unset +{ + unset dave +} +unset dave +[[ $(typeset +f) == *dave.* ]] && err_exit 'unset discipline not removed' +print 'print ${VAR}' > /tmp/script$$ +VAR=foo /tmp/script$$ > /tmp/out$$ +[[ $(</tmp/out$$) == foo ]] || err_exit 'environment variables not passed to scripts' +( + unset dave + function dave.append + { + .sh.value+=$dave + dave= + } + dave=foo; dave+=bar + [[ $dave == barfoo ]] || exit 2 +) 2> /dev/null +case $? in +0) ;; +1) err_exit 'append discipline not implemented';; +*) err_exit 'append discipline not working';; +esac +.sh.foobar=hello +{ + function .sh.foobar.get + { + .sh.value=world + } +} 2> /dev/null || err_exit "Can't add get discipline to .sh.foobar" +[[ ${.sh.foobar} == world ]] || err_exit 'get discipline for .sh.foobar not working' +x='a|b' +IFS='|' +set -- $x +[[ $2 == b ]] || err_exit '$2 should be b after set' +exec 3>&2 2> /dev/null +set -x +( IFS= ) 2> /dev/null +set +x +exec 2>&3- +set -- $x +[[ $2 == b ]] || err_exit '$2 should be b after subshell' +: & pid=$! +( : & ) +[[ $pid == $! ]] || err_exit '$! value not preserved across subshells' +unset foo +typeset -A foo +function foo.set +{ + case ${.sh.subscript} in + bar) if ((.sh.value > 1 )) + then .sh.value=5 + foo[barrier_hit]=yes + fi + ;; + barrier_hit) + if [[ ${.sh.value} = yes ]] + then foo[barrier_not_hit]=no + else foo[barrier_not_hit]=yes + fi + ;; + esac +} +foo[barrier_hit]=no +foo[bar]=1 +(( foo[bar] == 1 )) || err_exit 'foo[bar] should be 1' +[[ ${foo[barrier_hit]} == no ]] || err_exit 'foo[barrier_hit] should be no' +[[ ${foo[barrier_not_hit]} == yes ]] || err_exit 'foo[barrier_not_hit] should be yes' +foo[barrier_hit]=no +foo[bar]=2 +(( foo[bar] == 5 )) || err_exit 'foo[bar] should be 5' +[[ ${foo[barrier_hit]} == yes ]] || err_exit 'foo[barrier_hit] should be yes' +[[ ${foo[barrier_not_hit]} == no ]] || err_exit 'foo[barrier_not_hit] should be no' +unset x +typeset -i x +function x.set +{ + typeset sub=${.sh.subscript} + (( sub > 0 )) && (( x[sub-1]= x[sub-1] + .sh.value )) +} +x[0]=0 x[1]=1 x[2]=2 x[3]=3 +[[ ${x[@]} == '12 8 5 3' ]] || err_exit 'set discipline for indexed array not working correctly' +((SECONDS=3*4)) +(( SECONDS < 12 || SECONDS > 12.1 )) && err_exit "SECONDS is $SECONDS and should be close to 12" +exit $((Errors)) |