summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common/tests
diff options
context:
space:
mode:
authorchin <none@none>2007-08-17 12:01:52 -0700
committerchin <none@none>2007-08-17 12:01:52 -0700
commitda2e3ebdc1edfbc5028edf1354e7dd2fa69a7968 (patch)
tree5280d3b78e289fe9551371ab6e7f15ef9944ea14 /usr/src/lib/libshell/common/tests
parent073dbf9103ef2a2b05d8a16e2d26db04e0374b0e (diff)
downloadillumos-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')
-rw-r--r--usr/src/lib/libshell/common/tests/alias.sh83
-rw-r--r--usr/src/lib/libshell/common/tests/append.sh72
-rw-r--r--usr/src/lib/libshell/common/tests/arith.sh466
-rw-r--r--usr/src/lib/libshell/common/tests/arrays.sh381
-rw-r--r--usr/src/lib/libshell/common/tests/attributes.sh216
-rw-r--r--usr/src/lib/libshell/common/tests/basic.sh336
-rw-r--r--usr/src/lib/libshell/common/tests/bracket.sh233
-rw-r--r--usr/src/lib/libshell/common/tests/builtins.sh451
-rw-r--r--usr/src/lib/libshell/common/tests/case.sh81
-rw-r--r--usr/src/lib/libshell/common/tests/comvar.sh197
-rw-r--r--usr/src/lib/libshell/common/tests/coprocess.sh218
-rw-r--r--usr/src/lib/libshell/common/tests/exit.sh81
-rw-r--r--usr/src/lib/libshell/common/tests/expand.sh123
-rw-r--r--usr/src/lib/libshell/common/tests/functions.sh758
-rw-r--r--usr/src/lib/libshell/common/tests/glob.sh303
-rw-r--r--usr/src/lib/libshell/common/tests/grep.sh102
-rw-r--r--usr/src/lib/libshell/common/tests/heredoc.sh213
-rw-r--r--usr/src/lib/libshell/common/tests/io.sh251
-rw-r--r--usr/src/lib/libshell/common/tests/nameref.sh229
-rw-r--r--usr/src/lib/libshell/common/tests/options.sh313
-rw-r--r--usr/src/lib/libshell/common/tests/path.sh186
-rw-r--r--usr/src/lib/libshell/common/tests/quoting.sh331
-rw-r--r--usr/src/lib/libshell/common/tests/quoting2.sh200
-rw-r--r--usr/src/lib/libshell/common/tests/return.sh177
-rw-r--r--usr/src/lib/libshell/common/tests/select.sh63
-rw-r--r--usr/src/lib/libshell/common/tests/shtests63
-rw-r--r--usr/src/lib/libshell/common/tests/substring.sh504
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_getconf.sh160
-rw-r--r--usr/src/lib/libshell/common/tests/tilde.sh87
-rw-r--r--usr/src/lib/libshell/common/tests/variables.sh558
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') != '&lt;&gt;&quot;&amp;&nbsp;&apos;&#9;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))