summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common/tests
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libshell/common/tests')
-rw-r--r--usr/src/lib/libshell/common/tests/README.tests53
-rw-r--r--usr/src/lib/libshell/common/tests/alias.sh18
-rw-r--r--usr/src/lib/libshell/common/tests/append.sh2
-rw-r--r--usr/src/lib/libshell/common/tests/arith.sh78
-rw-r--r--usr/src/lib/libshell/common/tests/arrays.sh35
-rw-r--r--usr/src/lib/libshell/common/tests/arrays2.sh2
-rw-r--r--usr/src/lib/libshell/common/tests/attributes.sh74
-rw-r--r--usr/src/lib/libshell/common/tests/basic.sh190
-rw-r--r--usr/src/lib/libshell/common/tests/bracket.sh104
-rw-r--r--usr/src/lib/libshell/common/tests/builtins.sh181
-rw-r--r--usr/src/lib/libshell/common/tests/case.sh2
-rw-r--r--usr/src/lib/libshell/common/tests/comvar.sh125
-rw-r--r--usr/src/lib/libshell/common/tests/coprocess.sh107
-rw-r--r--usr/src/lib/libshell/common/tests/cubetype.sh11
-rw-r--r--usr/src/lib/libshell/common/tests/enum.sh6
-rw-r--r--usr/src/lib/libshell/common/tests/exit.sh30
-rw-r--r--usr/src/lib/libshell/common/tests/expand.sh2
-rw-r--r--usr/src/lib/libshell/common/tests/functions.sh224
-rw-r--r--usr/src/lib/libshell/common/tests/glob.sh16
-rw-r--r--usr/src/lib/libshell/common/tests/grep.sh10
-rw-r--r--usr/src/lib/libshell/common/tests/heredoc.sh42
-rw-r--r--usr/src/lib/libshell/common/tests/io.sh254
-rw-r--r--usr/src/lib/libshell/common/tests/locale.sh104
-rw-r--r--usr/src/lib/libshell/common/tests/nameref.sh79
-rw-r--r--usr/src/lib/libshell/common/tests/options.sh289
-rw-r--r--usr/src/lib/libshell/common/tests/path.sh102
-rw-r--r--usr/src/lib/libshell/common/tests/pointtype.sh2
-rw-r--r--usr/src/lib/libshell/common/tests/quoting.sh13
-rw-r--r--usr/src/lib/libshell/common/tests/quoting2.sh10
-rw-r--r--usr/src/lib/libshell/common/tests/recttype.sh2
-rw-r--r--usr/src/lib/libshell/common/tests/restricted.sh19
-rw-r--r--usr/src/lib/libshell/common/tests/return.sh11
-rw-r--r--usr/src/lib/libshell/common/tests/select.sh11
-rw-r--r--usr/src/lib/libshell/common/tests/shtests31
-rw-r--r--usr/src/lib/libshell/common/tests/sigchld.sh54
-rw-r--r--usr/src/lib/libshell/common/tests/signal.sh125
-rw-r--r--usr/src/lib/libshell/common/tests/statics.sh14
-rw-r--r--usr/src/lib/libshell/common/tests/subshell.sh246
-rw-r--r--usr/src/lib/libshell/common/tests/substring.sh18
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_array_default_datatype.sh303
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_builtin_poll.sh72
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_builtin_sum.sh5
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_builtin_tail.sh446
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_command_substitution.sh291
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_compound_nameref.sh215
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_compoundvario.sh124
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6687139_command_substitution_exec_redirection_allocation_loop.sh11
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6713682_compound_var_bleeds_through_subshell.sh26
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6722134_background_CHLD_trap.sh10
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6753538_subshell_leaks_umask.sh10
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6754020_weird_square_bracket_expansion.sh9
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6763594_command_failure_execs_twice.sh12
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6766246_pattern_matching_bug.sh9
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6769332_substitutions_terminate_shell_after_257_iterations.sh124
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6777491_lacks_arithmetric_function_iszero.sh95
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6778077_sigthaw_trap.sh83
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6789247_printf_hexfloat_rounding.sh130
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6800929_large_command_substitution_hang.sh129
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6805792_varmovetest1.sh152
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6805794_character_to_wchar_not_working.sh106
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6805795_negative_zero.sh170
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6835835_builtin_cat_n_broken.sh139
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6848486_echo_test_with_test_undefined_executes_test_builtin.sh94
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6855875_typeset_hexfloat_has_too_few_digits.sh145
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6862121_shbinexec_kernel_module_defunct.sh111
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6881017_background_process_in_subshell_hangs_caller.sh82
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_getconf.sh35
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_local_compound_nameref001.sh8
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_staticvariables.sh5
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_vartree001.sh8
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_vartree002.sh36
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_vartree003.sh8
-rw-r--r--usr/src/lib/libshell/common/tests/tilde.sh27
-rw-r--r--usr/src/lib/libshell/common/tests/timetype.sh2
-rw-r--r--usr/src/lib/libshell/common/tests/treemove.sh85
-rw-r--r--usr/src/lib/libshell/common/tests/types.sh121
-rw-r--r--usr/src/lib/libshell/common/tests/variables.sh119
-rw-r--r--usr/src/lib/libshell/common/tests/vartree1.sh46
-rw-r--r--usr/src/lib/libshell/common/tests/vartree2.sh94
79 files changed, 5420 insertions, 973 deletions
diff --git a/usr/src/lib/libshell/common/tests/README.tests b/usr/src/lib/libshell/common/tests/README.tests
new file mode 100644
index 0000000000..c78d32d9b1
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/README.tests
@@ -0,0 +1,53 @@
+
+#### ksh93 test suite
+
+## Intro
+The directory /usr/demo/ksh/tests/ contains the ksh93 test suite
+which is used to verify the correct behaviour of ksh93.
+
+The test suite is split into modules with the ending *.sh
+and a frontend called "shtests" which is used to run the tests.
+
+
+## Basic description:
+/usr/demo/ksh/tests/shtests <options> <varname=value> <testmodule>
+
+<options> may be:
+ -a execute test module one time as normal script code
+ and a 2nd time as compiled shell script. The env
+ variable SHCOMP defines the version of the shell
+ compiler being used (default is "${SHELL%/*}/shcomp",
+ however it is recommended to explicitly set SHCOMP
+ to /usr/bin/shcomp).
+ -c execute test module as compiled shell script
+ -s execute test module as normal shell script
+ -t do not print timing information
+ -v use VMDEBUG
+<varname=value>
+ Sets one or more environment variables to value "value".
+<testmodule>
+ file name of test module
+
+
+## Basic usage in Solaris >= 11 and OpenSolaris/Indiana:
+The tests can be executed like this:
+$ export SHELL=<path-to-ksh93-executable>
+$ export SHCOMP=/usr/bin/shcomp
+for t in /usr/demo/ksh/tests/*.sh ; do
+ $SHELL /usr/demo/ksh/tests/shtests -a "$t"
+done
+
+Note that you MUST NOT use "/usr/bin/ksh93" as value for
+SHELL since /usr/bin/ksh93 on Solaris is a wrapper which
+selects a suitable executable in /usr/bin/<isa>/ksh93
+based on the hardware capabilities defined via /usr/bin/isalist
+
+Valid values for SHELL are:
+- SHELL=/usr/bin/i86/ksh93 # 32bit i386
+- SHELL=/usr/bin/amd64/ksh93 # 64bit AMD64
+- SHELL=/usr/bin/sparcv7/ksh93 # 32bit SPARC
+- SHELL=/usr/bin/sparcv9/ksh93 # 64bit SPARC
+- SHELL=/usr/bin/s390/ksh93 # 32bit SystemZ
+- SHELL=/usr/bin/s390x/ksh93 # 64bit SystemZ
+
+# EOF.
diff --git a/usr/src/lib/libshell/common/tests/alias.sh b/usr/src/lib/libshell/common/tests/alias.sh
index e001668ef7..f527faf23e 100644
--- a/usr/src/lib/libshell/common/tests/alias.sh
+++ b/usr/src/lib/libshell/common/tests/alias.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -27,6 +27,10 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
alias foo='print hello'
if [[ $(foo) != hello ]]
then err_exit 'foo, where foo is alias for "print hello" failed'
@@ -66,7 +70,7 @@ alias !!=print
if [[ $(!! hello 2>/dev/null) != hello ]]
then err_exit 'alias for !!=print not working'
fi
-alias foo=echo
+alias foo=echo
if [[ $(print "$(foo bar)" ) != bar ]]
then err_exit 'alias in command substitution not working'
fi
@@ -81,14 +85,12 @@ then [[ ! $(alias -t | grep rm= ) ]] && err_exit 'tracked alias not set'
[[ $(alias -t | grep rm= ) ]] && err_exit 'tracked alias not cleared'
fi
if hash -r 2>/dev/null && [[ ! $(hash) ]]
-then mkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed"
- trap "cd /; rm -rf /tmp/ksh$$" EXIT
- PATH=/tmp/ksh$$:/bin:/usr/bin
+then PATH=$tmp:/bin:/usr/bin
for i in foo -foo --
- do print ':' > /tmp/ksh$$/$i
- chmod +x /tmp/ksh$$/$i
+ do print ':' > $tmp/$i
+ chmod +x $tmp/$i
hash -r -- $i 2>/dev/null || err_exit "hash -r -- $i failed"
- [[ $(hash) == $i=/tmp/ksh$$/$i ]] || err_exit "hash -r -- $i failed, expected $i=/tmp/ksh$$/$i, got $(hash)"
+ [[ $(hash) == $i=$tmp/$i ]] || err_exit "hash -r -- $i failed, expected $i=$tmp/$i, got $(hash)"
done
else err_exit 'hash -r failed'
fi
diff --git a/usr/src/lib/libshell/common/tests/append.sh b/usr/src/lib/libshell/common/tests/append.sh
index 00c432520a..d3e10c9100 100644
--- a/usr/src/lib/libshell/common/tests/append.sh
+++ b/usr/src/lib/libshell/common/tests/append.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
diff --git a/usr/src/lib/libshell/common/tests/arith.sh b/usr/src/lib/libshell/common/tests/arith.sh
index c330abce90..47c9619c75 100644
--- a/usr/src/lib/libshell/common/tests/arith.sh
+++ b/usr/src/lib/libshell/common/tests/arith.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -26,8 +26,13 @@ function err_exit
alias err_exit='err_exit $LINENO'
Command=${0##*/}
-trap '' FPE # NOTE: osf.alpha requires this (no ieee math)
integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+trap '' FPE # NOTE: osf.alpha requires this (no ieee math)
+
integer x=1 y=2 z=3
if (( 2+2 != 4 ))
then err_exit 2+2!=4
@@ -135,7 +140,7 @@ if [[ $? == 0 ]]
then err_exit 'floating point allowed with % operator'
fi
x=.125
-if [[ $(( 4 * x/2 )) != 0.25 ]]
+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 ]]
@@ -190,7 +195,7 @@ then err_exit "&= not working"
fi
function newscope
{
- float x=1.5
+ float x=1.5
(( x += 1 ))
print -r -- $x
}
@@ -342,7 +347,7 @@ 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
+done
unset x
x=010
(( x == 8 )) || err_exit 'leading zeros not treated as octal arithmetic'
@@ -365,8 +370,7 @@ i=2
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$$ <<-\!
+cat > $tmp/script <<-\!
tests=$*
typeset -A blop
function blop.get
@@ -412,14 +416,14 @@ function mkobj
}
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'
+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'
@@ -434,7 +438,7 @@ 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 '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) ))
@@ -483,4 +487,46 @@ $SHELL -c '(( x=));:' 2> /dev/null && err_exit '((x=)) should be an error'
$SHELL -c '(( x+=));:' 2> /dev/null && err_exit '((x+=)) should be an error'
$SHELL -c '(( x=+));:' 2> /dev/null && err_exit '((x=+)) should be an error'
$SHELL -c 'x=();x.arr[0]=(z=3); ((x.arr[0].z=2))' 2> /dev/null || err_exit '(((x.arr[0].z=2)) should not be an error'
+
+float t
+typeset a b r
+v="-0.0 0.0 +0.0 -1.0 1.0 +1.0"
+for a in $v
+do for b in $v
+ do (( r = copysign(a,b) ))
+ (( t = copysign(a,b) ))
+ [[ $r == $t ]] || err_exit $(printf "float t=copysign(%3.1f,%3.1f) => %3.1f -- expected %3.1f\n" a b t r)
+ done
+done
+
+typeset -l y y_ascii
+(( y=sin(90) ))
+y_ascii=$y
+(( y == y_ascii )) || err_exit "no match,\n\t$(printf "%a\n" y)\n!=\n\t$(printf "%a\n" y_ascii)"
+
+( $SHELL <<- \EOF
+ p=5
+ t[p]=6
+ while (( t[p] != 0 )) ; do
+ ((
+ p+=1 ,
+ t[p]+=2 ,
+ p+=3 ,
+ t[p]+=5 ,
+ p+=1 ,
+ t[p]+=2 ,
+ p+=1 ,
+ t[p]+=1 ,
+ p-=6 ,
+ t[p]-=1
+ ))
+ :
+ done
+EOF) 2> /dev/null || err_exit 'error with comma expression'
+
+N=(89551 89557)
+i=0 j=1
+[[ $(printf "%d" N[j]-N[i]) == 6 ]] || err_exit 'printf %d N[i]-N[j] failed'
+[[ $((N[j]-N[i])) == 6 ]] || err_exit '$((N[j]-N[i])) incorrect'
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/arrays.sh b/usr/src/lib/libshell/common/tests/arrays.sh
index 14504edc00..996101409f 100644
--- a/usr/src/lib/libshell/common/tests/arrays.sh
+++ b/usr/src/lib/libshell/common/tests/arrays.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -25,6 +25,12 @@ function err_exit
}
alias err_exit='err_exit $LINENO'
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
function fun
{
integer i
@@ -34,8 +40,6 @@ function fun
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'
@@ -268,7 +272,7 @@ fi
export foo
typeset -i foo
[[ $($SHELL -c "print $foo") == 143 ]]'
-) 2> /dev/null ||
+) 2> /dev/null ||
err_exit 'exporting associative array not exporting 0-th element'
unset foo
typeset -A foo
@@ -283,7 +287,7 @@ for i in one three four five
do : ${foo[$i]}
done
if [[ ${!foo[@]} != two ]]
-then err_exit 'Error in subscript names'
+then err_exit 'error in subscript names'
fi
unset x
x=( 1 2 3)
@@ -329,24 +333,23 @@ 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'
+print 'print ${var[0]} ${var[1]}' > $tmp/script
+chmod +x $tmp/script
+[[ $($SHELL -c "var=(foo bar);export var;$tmp/script") == 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$$ <<- \!
+cat > $tmp/script <<- \!
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'
+[[ $($SHELL -c "typeset -A foo;$tmp/script") == foo ]] 2> /dev/null || err_exit 'empty associative arrays not being cleared correctly before scripts'
+[[ $($SHELL -c "typeset -A foo;foo[abc]=abc;$tmp/script") == 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'
@@ -406,7 +409,7 @@ x=${bar[$foo[5]]}
test_array[3]=4
print "val=${test_array[3]}"
++EOF+++
-) == val=4 ]] 2> /dev/null || err_exit 'after reading array[j] and assign array[j] fails'
+) == val=4 ]] 2> /dev/null || err_exit 'after reading array[j] and assign array[j] fails'
[[ $($SHELL <<- \+++EOF+++
pastebin=( typeset -a form)
pastebin.form+=( name="name" data="clueless" )
@@ -464,4 +467,10 @@ a[6]=six
[[ ${a[-1]} == six ]] || err_exit 'a[-1] should be six'
[[ ${a[-3]} == four ]] || err_exit 'a[-3] should be four'
[[ ${a[-3..-1]} == 'four six' ]] || err_exit "a[-3,-1] should be 'four six'"
+
+FILTER=(typeset scope)
+FILTER[0].scope=include
+FILTER[1].scope=exclude
+[[ ${#FILTER[@]} == 2 ]] || err_exit "FILTER array should have two elements not ${#FILTER[@]}"
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/arrays2.sh b/usr/src/lib/libshell/common/tests/arrays2.sh
index 56bce796ae..ee8f0ae315 100644
--- a/usr/src/lib/libshell/common/tests/arrays2.sh
+++ b/usr/src/lib/libshell/common/tests/arrays2.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
diff --git a/usr/src/lib/libshell/common/tests/attributes.sh b/usr/src/lib/libshell/common/tests/attributes.sh
index 2d4f1e3d21..474972c03b 100644
--- a/usr/src/lib/libshell/common/tests/attributes.sh
+++ b/usr/src/lib/libshell/common/tests/attributes.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -27,6 +27,10 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
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
@@ -115,18 +119,18 @@ 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'
+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$$
+print 'typeset -i m=48/4+1;print -- $m' > $tmp/script
+chmod +x $tmp/script
typeset -Z2 m
-if [[ $(/tmp/ksh$$) != 13 ]]
+if [[ $($tmp/script) != 13 ]]
then err_exit 'attributes not cleared for script execution'
fi
-print 'print VAR=$VAR' > /tmp/ksh$$
+print 'print VAR=$VAR' > $tmp/script
typeset -L70 VAR=var
-/tmp/ksh$$ > /tmp/ksh$$.1
-[[ $(< /tmp/ksh$$.1) == VAR= ]] || err_exit 'typeset -L should not be inherited'
+$tmp/script > $tmp/script.1
+[[ $(< $tmp/script.1) == VAR= ]] || err_exit 'typeset -L should not be inherited'
typeset -Z LAST=00
unset -f foo
function foo
@@ -145,7 +149,6 @@ if (( ${#LAST} != 2 ))
then err_exit 'LAST!=2'
fi
[[ $(set | grep LAST) == LAST=02 ]] || err_exit "LAST not correct in set list"
-rm -rf /tmp/ksh$$*
set -a
unset foo
foo=bar
@@ -195,7 +198,9 @@ 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'
+if env '!=1' >/dev/null 2>&1
+then [[ $(env '!=1' $SHELL -c 'echo ok' 2>/dev/null) == ok ]] || err_exit 'malformed environment terminates shell'
+fi
unset var
typeset -b var
printf '12%Z34' | read -r -N 5 var
@@ -211,10 +216,10 @@ unset foo bar
unset -f fun
function fun
{
- export foo=hello
+ 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'
@@ -224,9 +229,9 @@ fred[66]=88
unset x y z
typeset -LZ3 x=abcd y z=00abcd
y=03
-[[ $y == "3 " ]] || err_exit '-LZ3 not working for value 03'
-[[ $x == "abc" ]] || err_exit '-LZ3 not working for value abcd'
-[[ $x == "abc" ]] || err_exit '-LZ3 not working for value 00abcd'
+[[ $y == "3 " ]] || err_exit '-LZ3 not working for value 03'
+[[ $x == "abc" ]] || err_exit '-LZ3 not working for value abcd'
+[[ $x == "abc" ]] || err_exit '-LZ3 not working for value 00abcd'
unset x z
set +a
[[ $(typeset -p z) ]] && err_exit "typeset -p for z undefined failed"
@@ -280,4 +285,43 @@ function foo
}
bar=xxx
[[ $(foo) == bar=xxx ]] || err_exit 'typeset -p not working inside a function'
+unset foo
+typeset -L5 foo
+[[ $(typeset -p foo) == 'typeset -L 5 foo' ]] || err_exit 'typeset -p not working for variables with attributes but without a value'
+{ $SHELL <<- EOF
+ typeset -L3 foo=aaa
+ typeset -L6 foo=bbbbbb
+ [[ \$foo == bbbbbb ]]
+EOF
+} || err_exit 'typeset -L should not preserve old attributes'
+{ $SHELL <<- EOF
+ typeset -R3 foo=aaa
+ typeset -R6 foo=bbbbbb
+ [[ \$foo == bbbbbb ]]
+EOF
+} 2> /dev/null || err_exit 'typeset -R should not preserve old attributes'
+
+expected='YWJjZGVmZ2hpag=='
+unset foo
+typeset -b -Z10 foo
+read foo <<< 'abcdefghijklmnop'
+[[ $foo == "$expected" ]] || err_exit 'read foo, where foo is "typeset -b -Z10" not working'
+unset foo
+typeset -b -Z10 foo
+read -N10 foo <<< 'abcdefghijklmnop'
+[[ $foo == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -Z10" not working'
+unset foo
+typeset -b -A foo
+read -N10 foo[4] <<< 'abcdefghijklmnop'
+[[ ${foo[4]} == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -A" foo not working'
+unset foo
+typeset -b -a foo
+read -N10 foo[4] <<< 'abcdefghijklmnop'
+[[ ${foo[4]} == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -a" foo not working'
+[[ $(printf %B foo[4]) == abcdefghij ]] || err_exit 'printf %B for binary associative array element not working'
+[[ $(printf %B foo[4]) == abcdefghij ]] || err_exit 'printf %B for binary indexed array element not working'
+unset foo
+
+$SHELL 2> /dev/null -c 'export foo=(bar=3)' && err_exit 'compound variables cannot be exported'
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/basic.sh b/usr/src/lib/libshell/common/tests/basic.sh
index 3911f9c472..597833e74f 100644
--- a/usr/src/lib/libshell/common/tests/basic.sh
+++ b/usr/src/lib/libshell/common/tests/basic.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -25,9 +25,13 @@ function err_exit
}
alias err_exit='err_exit $LINENO'
-# test basic file operations like redirection, pipes, file expansion
Command=${0##*/}
integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test basic file operations like redirection, pipes, file expansion
set -- \
go+r 0000 \
go-r 0044 \
@@ -53,11 +57,9 @@ 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"
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
um=$(umask -S)
( umask 0777; > foobar )
rm -f foobar
@@ -70,11 +72,11 @@ rm -f foobar
for i in 1 2
do print foobar*
rm -f foobar
-done > out$$
-if [[ "$(<out$$)" != "foobar"$'\n'"foobar*" ]]
+done > out
+if [[ "$(<out)" != "foobar"$'\n'"foobar*" ]]
then print -u2 "optimizer bug with file expansion"
fi
-rm -f out$$ foobar
+rm -f out foobar
mkdir dir
if [[ $(print */) != dir/ ]]
then err_exit 'file expansion with trailing / not working'
@@ -100,7 +102,7 @@ set -- dat*
if (( $# != 5 ))
then err_exit "dat* matches only $# files"
fi
-if (command > foo\\abc) 2> /dev/null
+if (command > foo\\abc) 2> /dev/null
then set -- foo*
if [[ $1 != 'foo\abc' ]]
then err_exit 'foo* does not match foo\abc'
@@ -113,15 +115,14 @@ then set -- TT*
fi
fi
cd ~- || err_exit "cd back failed"
-cat > /tmp/ksh$$/script <<- !
+cat > $tmp/script <<- !
#! $SHELL
print -r -- \$0
!
-chmod 755 /tmp/ksh$$/script
-if [[ $(/tmp/ksh$$/script) != "/tmp/ksh$$/script" ]]
+chmod 755 $tmp/script
+if [[ $($tmp/script) != "$tmp/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 ]]
@@ -140,9 +141,9 @@ fi
( sleep 2; cat <<!
foobar
!
-) | cat > /tmp/foobar$$ &
+) | cat > $tmp/foobar &
wait $!
-foobar=$( < /tmp/foobar$$)
+foobar=$( < $tmp/foobar)
if [[ $foobar != foobar ]]
then err_exit "$foobar is not foobar"
fi
@@ -150,26 +151,26 @@ 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."
+} > $tmp/foobar
+if [[ $( < $tmp/foobar) != $'foo\nbar\nbam' ]]
+then err_exit "output file pointer not shared correctly"
fi
-cat > /tmp/foobar$$ <<\!
+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."
+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."
+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."
+if [[ $( $tmp/foobar) != $'foo\nbar\nbam' ]]
+then err_exit "output file pointer not shared correctly"
fi
-rm -f /tmp/foobar$$
+rm -f $tmp/foobar
x=$( (print foo) ; (print bar) )
if [[ $x != $'foo\nbar' ]]
then err_exit " ( (print foo);(print bar ) failed"
@@ -182,7 +183,7 @@ x=$( (/bin/echo foo) ; (/bin/echo bar) )
if [[ $x != $'foo\nbar' ]]
then err_exit " ( (/bin/echo);(/bin/echo bar ) failed"
fi
-cat > /tmp/ksh$$ <<\!
+cat > $tmp/script <<\!
if [[ -p /dev/fd/0 ]]
then builtin cat
cat - > /dev/null
@@ -190,33 +191,30 @@ then builtin cat
else print no
fi
!
-chmod +x /tmp/ksh$$
-case $( (print) | /tmp/ksh$$;:) in
+chmod +x $tmp/script
+case $( (print) | $tmp/script;:) 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 ]]
+print 'print $0' > $tmp/script
+print ". $tmp/script" > $tmp/scriptx
+chmod +x $tmp/scriptx
+if [[ $($tmp/scriptx) != $tmp/scriptx ]]
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
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+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"
+then err_exit "nested scripts failed"
fi
x=$( (./a) | cat)
if [[ $x != "hello there" ]]
-then err_exit "scripts in subshells fail"
+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"
@@ -239,29 +237,29 @@ 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$$ <<- \!
+cat > $tmp/script <<- \!
read line 2> /dev/null
print done
!
-if [[ $($SHELL /tmp/ksh$$ <&-) != done ]]
+if [[ $($SHELL $tmp/script <&-) != done ]]
then err_exit "executing script with 0 closed fails"
fi
trap '' INT
-cat > /tmp/ksh$$ <<- \!
+cat > $tmp/script <<- \!
trap 'print bad' INT
kill -s INT $$
print good
!
-chmod +x /tmp/ksh$$
-if [[ $($SHELL /tmp/ksh$$) != good ]]
+chmod +x $tmp/script
+if [[ $($SHELL $tmp/script) != good ]]
then err_exit "traps ignored by parent not ignored"
fi
trap - INT
-cat > /tmp/ksh$$ <<- \!
+cat > $tmp/script <<- \!
read line
/bin/cat
!
-if [[ $($SHELL /tmp/ksh$$ <<!
+if [[ $($SHELL $tmp/script <<!
one
two
!
@@ -305,7 +303,7 @@ wait # not running --pipefail which would interfere with subsequent tests
sleep 20 &
pids=$!
if [[ $(jobs -p) != $! ]]
-then err_exit 'jobs -p not reporting a background job'
+then err_exit 'jobs -p not reporting a background job'
fi
sleep 20 &
pids="$pids $!"
@@ -323,32 +321,31 @@ kill $pids
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 <<- \!!!
+ [[ $($SHELL -c $'tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!!
line0
line1
line2
!!!
wait
- cat /tmp/ksh'$$x 2> /dev/null) == line1 ]] || err_exit '>() process substitution fails'
- > /tmp/ksh$$x
+ cat '$tmp/scriptx 2> /dev/null) == line1 ]] || err_exit '>() process substitution fails'
+ > $tmp/scriptx
[[ $($SHELL -c $'
for i in 1
- do tee >(grep \'1$\' > /tmp/ksh'$$'x) > /dev/null <<- \!!!
+ do tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!!
line0
line1
line2
!!!
done
wait
- cat /tmp/ksh'$$x 2>> /dev/null) == line1 ]] || err_exit '>() process substitution fails in for loop'
+ cat '$tmp/scriptx 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'
+print cat > $tmp/scriptx
+chmod +x $tmp/scriptx
+[[ $($SHELL -c "print foo | $tmp/scriptx ;:" 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'
exec 3<&-
@@ -357,19 +354,18 @@ then [[ $(cat <(print hello) ) == hello ]] || err_exit "process substitution not
$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"
-cat > /tmp/ksh$$x <<- \EOF
+print 'print foo "$@"' > $tmp/scriptx
+[[ $( print "($tmp/scriptx bar)" | $SHELL 2>/dev/null) == 'foo bar' ]] || err_exit 'script pipe to shell fails'
+print "#! $SHELL" > $tmp/scriptx
+print 'print -- $0' >> $tmp/scriptx
+chmod +x $tmp/scriptx
+[[ $($tmp/scriptx) == $tmp/scriptx ]] || err_exit "\$0 is $0 instead of $tmp/scriptx"
+cat > $tmp/scriptx <<- \EOF
myfilter() { x=$(print ok | cat); print -r -- $SECONDS;}
set -o pipefail
sleep 3 | myfilter
EOF
-(( $($SHELL /tmp/ksh$$x) > 2.0 )) && err_exit 'command substitution causes pipefail option to hang'
-rm -f /tmp/ksh$$x
+(( $($SHELL $tmp/scriptx) > 2.0 )) && err_exit 'command substitution causes pipefail option to hang'
exec 3<&-
( typeset -r foo=bar) 2> /dev/null || err_exit 'readonly variables set in a subshell cannot unset'
$SHELL -c 'x=${ print hello;}; [[ $x == hello ]]' 2> /dev/null || err_exit '${ command;} not supported'
@@ -406,13 +402,8 @@ $SHELL 2> /dev/null <<- \EOF || err_exit '${ command;}xxx not working'
EOF
unset foo
-function foo
-{
- print bar
-}
-[[ ${foo} == bar ]] || err_exit '${foo} is not command substitution when foo unset'
-[[ ! ${foo[@]} ]] || err_exit '${foo[@]} is not empty when foo is unset'
-[[ ! ${foo[3]} ]] || err_exit '${foo[3]} is not empty when foo is unset'
+[[ ! ${foo[@]} ]] || err_exit '${foo[@]} is not empty when foo is unset'
+[[ ! ${foo[3]} ]] || err_exit '${foo[3]} is not empty when foo is unset'
[[ $(print "[${ print foo }]") == '[foo]' ]] || err_exit '${...} not working when } is followed by ]'
[[ $(print "${ print "[${ print foo }]" }") == '[foo]' ]] || err_exit 'nested ${...} not working when } is followed by ]'
unset foo
@@ -421,10 +412,57 @@ expected=foreback
got=$(print -n fore;(sleep 2;print back)&)
[[ $got == $expected ]] || err_exit "command substitution background process output error -- got '$got', expected '$expected'"
-for false in false $(whence -p false)
+binfalse=$(whence -p false)
+for false in false $binfalse
do x=$($false) && err_exit "x=\$($false) should fail"
$($false) && err_exit "\$($false) should fail"
$($false) > /dev/null && err_exit "\$($false) > /dev/null should fail"
done
-[[ $(env 'x-a=y' $SHELL -c 'env | grep x-a') == *x-a=y* ]] || err_exit 'invalid environment variables not preserved'
+if env x-a=y >/dev/null 2>&1
+then [[ $(env 'x-a=y' $SHELL -c 'env | grep x-a') == *x-a=y* ]] || err_exit 'invalid environment variables not preserved'
+fi
+float s=SECONDS
+sleep=$(whence -p sleep)
+for i in 1 2
+do print $i
+done | while read sec; do ( $sleep $sec; $sleep $sec) done
+(( (SECONDS-s) < 4)) && err_exit '"command | while read...done" finishing too fast'
+s=SECONDS
+set -o pipefail
+for ((i=0; i < 30; i++))
+do print hello
+ sleep .1
+done | $sleep 1
+(( (SECONDS-s) < 2 )) || err_exit 'early termination not causing broken pipe'
+[[ $({ trap 'print trap' 0; print -n | $(whence -p cat); } & wait $!) == trap ]] || err_exit 'trap on exit not getting triggered'
+var=$({ trap 'print trap' ERR; print -n | $binfalse; } & wait $!)
+[[ $var == trap ]] || err_exit 'trap on ERR not getting triggered'
+
+exp=
+got=$(
+ function fun
+ {
+ $binfalse && echo FAILED
+ }
+ : works if this line deleted : |
+ fun
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to function with conditional fails -- expected '$exp', got '$got'"
+got=$(
+ : works if this line deleted : |
+ { $binfalse && echo FAILED; }
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to { ... } with conditional fails -- expected '$exp', got '$got'"
+
+got=$(
+ : works if this line deleted : |
+ ( $binfalse && echo FAILED )
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to ( ... ) with conditional fails -- expected '$exp', got '$got'"
+
+( $SHELL -c 'trap : DEBUG; x=( $foo); exit 0') 2> /dev/null || err_exit 'trap DEBUG fails'
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/bracket.sh b/usr/src/lib/libshell/common/tests/bracket.sh
index 0b36806fbf..496fdae5a4 100644
--- a/usr/src/lib/libshell/common/tests/bracket.sh
+++ b/usr/src/lib/libshell/common/tests/bracket.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -27,17 +27,19 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
null=''
if [[ ! -z $null ]]
then err_exit "-z: null string should be of zero length"
fi
-file=/tmp/regresso$$
-newer_file=/tmp/regressn$$
+file=$tmp/original
+newer_file=$tmp/newer
if [[ -z $file ]]
then err_exit "-z: $file string should not be of zero length"
fi
-trap "rm -f $file $newer_file" EXIT
-rm -f $file
if [[ -a $file ]]
then err_exit "-a: $file shouldn't exist"
fi
@@ -119,11 +121,11 @@ fi
if [[ $file -nt $newer_file ]]
then err_exit "$newer_file should be newer than $file"
fi
-if [[ $file != /tmp/* ]]
-then err_exit "$file should match /tmp/*"
+if [[ $file != $tmp/* ]]
+then err_exit "$file should match $tmp/*"
fi
-if [[ $file = '/tmp/*' ]]
-then err_exit "$file should not equal /tmp/*"
+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"
@@ -211,17 +213,17 @@ done
[[ 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'
+) || 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'
+[[ -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'
+[[ -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'
+[[ -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'
@@ -242,4 +244,80 @@ i=hell
test '(' = ')' && err_exit '"test ( = )" should not be true'
[[ $($SHELL -c 'case F in ~(Eilr)[a-z0-9#]) print ok;;esac' 2> /dev/null) == ok ]] || err_exit '~(Eilr) not working in case command'
[[ $($SHELL -c "case Q in ~(Fi)q | \$'\E') print ok;;esac" 2> /dev/null) == ok ]] || err_exit '~(Fi)q | \E not working in case command'
+
+for l in C en_US.ISO8859-15
+do [[ $($SHELL -c "LC_COLLATE=$l" 2>&1) ]] && continue
+ export LC_COLLATE=$l
+ set -- \
+ 'A' 0 1 1 0 1 1 1 0 0 1 0 0 \
+ 'Z' 0 1 1 0 1 1 1 0 0 1 0 0 \
+ '/' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '.' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '_' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '-' 1 1 1 1 1 1 0 0 0 0 0 0 \
+ '%' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '@' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '!' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '^' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ # retain this line #
+ while (( $# >= 13 ))
+ do c=$1
+ shift
+ for p in \
+ '[![.-.]]' \
+ '[![.-.][:upper:]]' \
+ '[![.-.]A-Z]' \
+ '[!-]' \
+ '[!-[:upper:]]' \
+ '[!-A-Z]' \
+ '[[.-.]]' \
+ '[[.-.][:upper:]]' \
+ '[[.-.]A-Z]' \
+ '[-]' \
+ '[-[:upper:]]' \
+ '[-A-Z]' \
+ # retain this line #
+ do e=$1
+ shift
+ [[ $c == $p ]]
+ g=$?
+ [[ $g == $e ]] || err_exit "[[ '$c' == $p ]] for LC_COLLATE=$l failed -- expected $e, got $g"
+ done
+ done
+done
+integer n
+if ( : < /dev/tty ) 2>/dev/null && exec {n}< /dev/tty
+then [[ -t $n ]] || err_exit "[[ -t n ]] fails when n > 9"
+fi
+foo=([1]=a [2]=b [3]=c)
+[[ -v foo[1] ]] || err_exit 'foo[1] should be set'
+[[ ${foo[1]+x} ]] || err_exit '${foo[1]+x} should be x'
+[[ ${foo[@]+x} ]] || err_exit '${foo[@]+x} should be x'
+unset foo[1]
+[[ -v foo[1] ]] && err_exit 'foo[1] should not be set'
+[[ ${foo[1]+x} ]] && err_exit '${foo[1]+x} should be empty'
+bar=(a b c)
+[[ -v bar[1] ]] || err_exit 'bar[1] should be set'
+[[ ${bar[1]+x} ]] || err_exit '${foo[1]+x} should be x'
+unset bar[1]
+[[ ${bar[1]+x} ]] && err_exit '${foo[1]+x} should be empty'
+[[ -v bar ]] || err_exit 'bar should be set'
+[[ -v bar[1] ]] && err_exit 'bar[1] should not be set'
+integer z=( 1 2 4)
+[[ -v z[1] ]] || err_exit 'z[1] should be set'
+unset z[1]
+[[ -v z[1] ]] && err_exit 'z[1] should not be set'
+typeset -si y=( 1 2 4)
+[[ -v y[6] ]] && err_exit 'y[6] should not be set'
+[[ -v y[1] ]] || err_exit 'y[1] should be set'
+unset y[1]
+[[ -v y[1] ]] && err_exit 'y[1] should not be set'
+x=abc
+[[ -v x[0] ]] || err_exit 'x[0] should be set'
+[[ ${x[0]+x} ]] || err_exit print '${x[0]+x} should be x'
+[[ -v x[3] ]] && err_exit 'x[3] should not be set'
+[[ ${x[3]+x} ]] && err_exit '${x[0]+x} should be Empty'
+unset x
+[[ ${x[@]+x} ]] && err_exit '${x[@]+x} should be Empty'
+unset x y z foo bar
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/builtins.sh b/usr/src/lib/libshell/common/tests/builtins.sh
index 08dac83a4e..cbd78fa98b 100644
--- a/usr/src/lib/libshell/common/tests/builtins.sh
+++ b/usr/src/lib/libshell/common/tests/builtins.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -25,9 +25,13 @@ function err_exit
}
alias err_exit='err_exit $LINENO'
-# test shell builtin commands
Command=${0##*/}
integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test shell builtin commands
builtin getconf
: ${foo=bar} || err_exit ": failed"
[[ $foo = bar ]] || err_exit ": side effects failed"
@@ -171,30 +175,31 @@ 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
+mkdir -p $tmp/a/b/c 2>/dev/null || err_exit "mkdir -p failed"
+$SHELL -c "cd $tmp/a/b; cd c" 2>/dev/null || err_exit "initial script relative cd fails"
+
+trap 'print TERM' TERM
+exp=$'trap -- \'print TERM\' TERM\ntrap -- \'cd /; rm -rf '$tmp$'\' EXIT'
+got=$(trap)
+[[ $got == $exp ]] || err_exit "\$(trap) failed -- expected \"$exp\", got \"$got\""
+exp='print TERM'
+got=$(trap -p TERM)
+[[ $got == $exp ]] || err_exit "\$(trap -p TERM) failed -- expected \"$exp\", got \"$got\""
+
[[ $($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 '( trap "" TERM);kill $$;print bad' == bad) ]] 2> /dev/null && err_exit 'trap ignored in subshell causes it to be ignored by parent'
${SHELL} -c 'kill -1 -$$' 2> /dev/null
-[[ $(kill -l $?) == HUP ]] || err_exit 'kill -1 -pid not working'
+[[ $(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'
+[[ $(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'
+[[ $(kill -l $?) == HUP ]] || err_exit 'kill -HUP -pid not working'
n=123
typeset -A base
base[o]=8#
@@ -266,23 +271,23 @@ 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' ]]
+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$ ^\^$ ^(.*\..*)!$' ]]
+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"
+then err_exit "printf '%..:c' not working"
fi
if [[ $(printf '%..*c\n' : abc) != a:b:c ]]
-then err_exit "printf '%..*c' not working"
+then err_exit "printf '%..*c' not working"
fi
if [[ $(printf '%..:s\n' abc def ) != abc:def ]]
-then err_exit "printf '%..:s' not working"
+then err_exit "printf '%..:s' not working"
fi
if [[ $(printf '%..*s\n' : abc def) != abc:def ]]
-then err_exit "printf '%..*s' not working"
+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?
@@ -296,12 +301,18 @@ behead()
}
print $'line1\nline2' | behead
if [[ $left != line2 ]]
-then err_exit "read reading ahead on a pipe"
+then err_exit "read reading ahead on a pipe"
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 ]]
+read -n1 y <<!
+abc
+!
+exp=a
+if [[ $y != $exp ]]
+then err_exit "read -n1 failed -- expected '$exp', got '$y'"
+fi
+print -n $'{ read -r line;print $line;}\nhello' > $tmp/script
+chmod 755 $tmp/script
+if [[ $($SHELL < $tmp/script) != hello ]]
then err_exit 'read of incomplete line not working correctly'
fi
set -f
@@ -321,19 +332,13 @@ 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\""
+v=$(getconf LIBPATH)
+for v in ${v//,/ }
+do v=${v#*:}
+ v=${v%%:*}
+ eval [[ \$$v ]] && env="$env $v=\"\$$v\""
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
@@ -364,7 +369,7 @@ do arg=$1 val=$2 code=$3
err=$(printf "$fmt" "$arg" 2>&1 >/dev/null)
printf "$fmt" "$arg" >/dev/null 2>&1
ret=$?
- [[ $out == $val ]] || err_exit "printf $fmt $arg failed -- expected $val, got $out"
+ [[ $out == $val ]] || err_exit "printf $fmt $arg failed -- expected '$val', got '$out'"
if (( $code ))
then [[ $err ]] || err_exit "printf $fmt $arg failed, error message expected"
else [[ $err ]] && err_exit "$err: printf $fmt $arg failed, error message not expected -- got '$err'"
@@ -398,6 +403,50 @@ do case $opt in
*) err_exit "getopts $options failed -- got flag $opt" ;;
esac
done
+
+unset a
+{ read -N3 a; read -N1 b;} <<!
+abcdefg
+!
+exp=abc
+[[ $a == $exp ]] || err_exit "read -N3 here-document failed -- expected '$exp', got '$a'"
+exp=d
+[[ $b == $exp ]] || err_exit "read -N1 here-document failed -- expected '$exp', got '$b'"
+read -n3 a <<!
+abcdefg
+!
+exp=abc
+[[ $a == $exp ]] || err_exit "read -n3 here-document failed -- expected '$exp', got '$a'"
+#(print -n a;sleep 1; print -n bcde) | { read -N3 a; read -N1 b;}
+#[[ $a == $exp ]] || err_exit "read -N3 from pipe failed -- expected '$exp', got '$a'"
+#exp=d
+#[[ $b == $exp ]] || err_exit "read -N1 from pipe failed -- expected '$exp', got '$b'"
+#(print -n a;sleep 1; print -n bcde) | read -n3 a
+#exp=a
+#[[ $a == $exp ]] || err_exit "read -n3 from pipe failed -- expected '$exp', got '$a'"
+#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
+# exp=a
+# [[ $a == $exp ]] || err_exit "read -n3 from fifo failed -- expected '$exp', got '$a'"
+# 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
+# exp=abc
+# [[ $a == $exp ]] || err_exit "read -N3 from fifo failed -- expected '$exp', got '$a'"
+# exp=d
+# [[ $b == $exp ]] || err_exit "read -N1 from fifo failed -- expected '$exp', got '$b'"
+#fi
+#rm -f $tmp/fifo
+
function longline
{
integer i
@@ -437,33 +486,43 @@ 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
-$SHELL -c 'sleep $(printf "%a" .95)' 2> /dev/null || err_exit "sleep doesn't except %a format constants"
-$SHELL -c 'test \( ! -e \)' 2> /dev/null ; [[ $? == 1 ]] || err_exit 'test \( ! -e \) not working'
+#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
+#$SHELL -c 'sleep $(printf "%a" .95)' 2> /dev/null || err_exit "sleep doesn't except %a format constants"
+#$SHELL -c 'test \( ! -e \)' 2> /dev/null ; [[ $? == 1 ]] || err_exit 'test \( ! -e \) not working'
[[ $(ulimit) == "$(ulimit -fS)" ]] || err_exit 'ulimit is not the same as ulimit -fS'
-tmpfile=${TMP-/tmp}/ksh$$.2
-trap 'rm -f /tmp/ksh$$ "$tmpfile"' EXIT
+tmpfile=$tmp/file.2
print $'\nprint -r -- "${.sh.file} ${LINENO} ${.sh.lineno}"' > $tmpfile
[[ $( . "$tmpfile") == "$tmpfile 2 1" ]] || err_exit 'dot command not working'
print -r -- "'xxx" > $tmpfile
[[ $($SHELL -c ". $tmpfile"$'\n print ok' 2> /dev/null) == ok ]] || err_exit 'syntax error in dot command affects next command'
-float sec=$SECONDS del=4
-exec 3>&2 2>/dev/null
-$SHELL -c "( sleep 1; kill -ALRM \$\$ ) & sleep $del" 2> /dev/null
-exitval=$?
-(( sec = SECONDS - sec ))
-exec 2>&3-
-(( exitval )) && err_exit "sleep doesn't exit 0 with ALRM interupt"
-(( sec > (del - 1) )) || err_exit "ALRM signal causes sleep to terminate prematurely -- expected 3 sec, got $sec"
+#float sec=$SECONDS del=4
+#exec 3>&2 2>/dev/null
+#$SHELL -c "( sleep 1; kill -ALRM \$\$ ) & sleep $del" 2> /dev/null
+#exitval=$?
+#(( sec = SECONDS - sec ))
+#exec 2>&3-
+#(( exitval )) && err_exit "sleep doesn't exit 0 with ALRM interupt"
+#(( sec > (del - 1) )) || err_exit "ALRM signal causes sleep to terminate prematurely -- expected 3 sec, got $sec"
+typeset -r z=3
+y=5
+for i in 123 z %x a.b.c
+do ( unset $i) 2>/dev/null && err_exit "unset $i should fail"
+done
+a=()
+for i in y y y[8] t[abc] y.d a.b a
+do unset $i || print -u2 "err_exit unset $i should not fail"
+done
+[[ $($SHELL -c 'y=3; unset 123 y;print $?$y') == 1 ]] 2> /dev/null || err_exit 'y is not getting unset with unset 123 y'
+[[ $($SHELL -c 'trap foo TERM; (trap;(trap) )') == 'trap -- foo TERM' ]] || err_exit 'traps not getting reset when subshell is last process'
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/case.sh b/usr/src/lib/libshell/common/tests/case.sh
index cca84686bd..1f04cfd30d 100644
--- a/usr/src/lib/libshell/common/tests/case.sh
+++ b/usr/src/lib/libshell/common/tests/case.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
diff --git a/usr/src/lib/libshell/common/tests/comvar.sh b/usr/src/lib/libshell/common/tests/comvar.sh
index dfc9d9acfd..00eac1d188 100644
--- a/usr/src/lib/libshell/common/tests/comvar.sh
+++ b/usr/src/lib/libshell/common/tests/comvar.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -85,7 +85,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 ||
+$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'
@@ -194,7 +194,7 @@ localvar
[[ $($SHELL -c 'foo=();foo.[x]=(y z); print ${foo.x[@]}') == 'y z' ]] 2> /dev/null || err_exit 'foo=( [x]=(y z) not working'
function staticvar
{
- if [[ $1 ]]
+ if [[ $1 ]]
then print -r -- "$point"
return
fi
@@ -291,7 +291,7 @@ foo=(
)
eval foo2="$foo"
foo2.hello=notok foo2.yes.yex=no foo2.extra=yes.
-typeset -C bar bam
+typeset -C bar bam
{
read -Cu3 bar
read -Cu3 bam
@@ -422,5 +422,120 @@ data.samples+=(
command2="grrrr2"
)
-[[ $data == %(()) ]] || err_exit "unbalanced parenthesis with compound variable containing array of compound variables"
+[[ $data == %(()) ]] || err_exit "unbalanced parenthesis with compound variable containing array of compound variables"
+typeset -C -A hello=( [foo]=bar)
+[[ $(typeset -p hello) == 'typeset -C -A hello=([foo]=bar)' ]] || err_exit 'typeset -A -C with intial assignment not working'
+# this caused a core dump before ksh93t+
+[[ $($SHELL -c 'foo=(x=3 y=4);function bar { typeset z=4;: $z;};bar;print ${!foo.@}') == 'foo.x foo.y' ]] 2> /dev/null || err_exit '${!foo.@} after function not working'
+
+function foo
+{
+ typeset tmp
+ read -C tmp
+ read -C tmp
+}
+foo 2> /dev/null <<- \EOF || err_exit 'deleting compound variable in function failed'
+ (
+ typeset -A myarray3=(
+ [a]=( foo=bar)
+ [b]=( foo=bar)
+ [c d]=( foo=bar)
+ [e]=( foo=bar)
+ [f]=( foo=bar)
+ [g]=( foo=bar)
+ [h]=( foo=bar)
+ [i]=( foo=bar)
+ [j]=( foo=bar)
+ )
+ )
+ hello
+EOF
+
+typeset -C -a mica01
+mica01[4]=( a_string="foo bar" )
+typeset -C more_content=(
+ some_stuff="hello"
+)
+mica01[4]+=more_content
+expected=$'typeset -C -a mica01=([4]=(a_string=\'foo bar\';some_stuff=hello;))'
+[[ $(typeset -p mica01) == "$expected" ]] || err_exit 'appened to indexed array compound variable not working'
+
+unset x
+compound x=( integer x ; )
+[[ ! -v x.x ]] && err_exit 'x.x should be set'
+expected=$'(\n\ttypeset -l -i x=0\n)'
+[[ $(print -v x) == "$expected" ]] || err_exit "'print -v x' should be $expected"
+
+typeset -C -A hello19=(
+ [19]=(
+ one="xone 19"
+ two="xtwo 19"
+ )
+ [23]=(
+ one="xone 23"
+ two="xtwo 23"
+ )
+)
+expected="typeset -C -A hello19=([19]=(one='xone 19';two='xtwo 19';) [23]=(one='xone 23';two='xtwo 23';))"
+[[ $(typeset -p hello19) == "$expected" ]] || print -u2 'typeset -p hello19 incorrect'
+expected=$'(\n\tone=\'xone 19\'\n\ttwo=\'xtwo 19\'\n) (\n\tone=\'xone 23\'\n\ttwo=\'xtwo 23\'\n)'
+[[ ${hello19[@]} == "$expected" ]] || print -u2 '${hello19[@]} incorrect'
+
+typeset -C -A foo1=( abc="alphabet" ) foo2=( abc="alphabet" )
+function add_one
+{
+ nameref left_op=$1
+ typeset -C info
+ info.hello="world"
+ nameref x=info
+ left_op+=x
+}
+nameref node1="foo1[1234]"
+add_one "node1"
+add_one "foo2[1234]"
+[[ "${foo1[1234]}" == "${foo2[1234]}" ]] || err_exit "test failed\n$(diff -u <( print -r -- "${foo1[1234]}") <(print -r -- "${foo2[1234]}"))."
+
+typeset -C tree
+function f1
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ typeset -C node
+ node.one="hello"
+ node.two="world"
+
+ # move local note into the array
+ typeset -m tr.subtree["a_node"]=node
+}
+f1 tree
+expected=$'(\n\ttypeset -A subtree=(\n\t\t[a_node]=(\n\t\t\tone=hello\n\t\t\ttwo=world\n\t\t)\n\t)\n)'
+[[ $tree == "$expected" ]] || err_exit 'move of compound local variable to global variable not working'
+
+typeset -C -A array
+float array[12].amount=2.9
+expected='typeset -C -A array=([12]=(typeset -l -E amount=2.9;))'
+[[ $(typeset -p array) == "$expected" ]] || err_exit 'typeset with compound variable with compound variable array not working'
+
+typeset -T foo_t=(
+ function diff
+ {
+ print 1.0
+ return 0
+ }
+)
+foo_t sw
+compound output=(
+ integer one=1
+ float mydiff=sw.diff
+ float end=.314
+)
+[[ $output == *end=* ]] || err_exit "The field 'name' end is missing"
+
+compound cpv1=( integer f=2 )
+compound x=(
+ integer a=1
+ compound b=cpv1
+)
+[[ $x == *f=2* ]] || err_exit "The field b containg 'f=2' is missing"
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/coprocess.sh b/usr/src/lib/libshell/common/tests/coprocess.sh
index feff0bace2..dde9a49805 100644
--- a/usr/src/lib/libshell/common/tests/coprocess.sh
+++ b/usr/src/lib/libshell/common/tests/coprocess.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -29,6 +29,9 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
if [[ -d /cygdrive ]]
then err_exit cygwin detected - coprocess tests disabled - enable at the risk of wedging your system
exit $((Errors))
@@ -46,11 +49,11 @@ function ping # id
cat |&
print -p "hello"
read -p line
-[[ $line == hello ]] || err_exit 'coprocessing fails'
+[[ $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'
+[[ $line == 'hello again' ]] || err_exit 'coprocess after moving fds fails'
exec 5<&- 6<&-
wait $!
@@ -87,8 +90,7 @@ do (( count-- ))
done
kill $(jobs -p) 2>/dev/null
-file=/tmp/regress$$
-trap "rm -f $file" EXIT
+file=$tmp/regress
cat > $file <<\!
/bin/cat |&
!
@@ -100,15 +102,24 @@ exec 5<&- 6>&-
kill $(jobs -p) 2>/dev/null
${SHELL-ksh} |&
-print -p $'print hello | cat\nprint Done'
+cop=$!
+exp=Done
+print -p $'print hello | cat\nprint '$exp
read -t 5 -p
read -t 5 -p
-if [[ $REPLY != Done ]]
-then err_exit "${SHELL-ksh} coprocess not working"
+got=$REPLY
+if [[ $got != $exp ]]
+then err_exit "${SHELL-ksh} coprocess io failed -- got '$got', expected '$exp'"
fi
exec 5<&p 6>&p
exec 5<&- 6>&-
-wait $!
+{ sleep 4; kill $cop; } 2>/dev/null &
+spy=$!
+if wait $cop 2>/dev/null
+then kill $spy 2>/dev/null
+else err_exit "coprocess hung after 'exec 5<&p 6>&p; exec 5<&- 6>&-'"
+fi
+wait
{
echo line1 | grep 'line2'
@@ -123,7 +134,7 @@ then err_exit "read -p hanging (SECONDS=$SECONDS count=$count)"
fi
wait $!
-( sleep 3 |& sleep 1 && kill $!; sleep 1; sleep 3 |& sleep 1 && kill $! ) ||
+( sleep 3 |& sleep 1 && kill $!; sleep 1; sleep 3 |& sleep 1 && kill $! ) ||
err_exit "coprocess cleanup not working correctly"
{ : |& } 2>/dev/null ||
err_exit "subshell coprocess lingers in parent"
@@ -163,7 +174,7 @@ r=
print -u6 ok
exec 6>&-
sleep 1
- kill $! 2> /dev/null
+ kill $! 2> /dev/null
) && err_exit 'coprocess with subshell would hang'
for sig in IOT ABRT
do if ( trap - $sig ) 2> /dev/null
@@ -178,7 +189,7 @@ do if ( trap - $sig ) 2> /dev/null
kill -$sig $$
kill $pid
sleep 2
- kill $$
+ kill $$
) &
read -p
++EOF++
@@ -206,7 +217,7 @@ trap - TERM
trap 'sleep_pid=; kill $pid; err_exit "coprocess 2 hung"' TERM
{ sleep 5; kill $$; } &
sleep_pid=$!
-cat |&
+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'
@@ -218,7 +229,7 @@ trap - TERM
trap 'sleep_pid=; kill $pid; err_exit "coprocess 3 hung"' TERM
{ sleep 5; kill $$; } &
sleep_pid=$!
-cat |&
+cat |&
pid=$!
print -p foo
print -p bar
@@ -231,4 +242,72 @@ wait $pid 2> /dev/null
trap - TERM
[[ $sleep_pid ]] && kill $sleep_pid
+exp=ksh
+got=$(print -r $'#00315
+COATTRIBUTES=\'label=make \'
+# @(#)$Id: libcoshell (AT&T Research) 2008-04-28 $
+_COSHELL_msgfd=5
+{ { (eval \'function fun { trap \":\" 0; return 1; }; trap \"exit 0\" 0; fun; exit 1\') && PATH= print -u$_COSHELL_msgfd ksh; } || { times && echo bsh >&$_COSHELL_msgfd; } || { echo osh >&$_COSHELL_msgfd; }; } >/dev/null 2>&1' | $SHELL 5>&1)
+[[ $got == $exp ]] || err_exit "coshell(3) identification sequence failed -- expected '$exp', got '$got'"
+
+function cop
+{
+ read
+ print ok
+}
+
+exp=ok
+
+cop |&
+pid=$!
+if print -p yo 2>/dev/null
+then read -p got
+else got='no coprocess'
+fi
+[[ $got == $exp ]] || err_exit "main coprocess main query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+
+cop |&
+pid=$!
+(
+if print -p yo 2>/dev/null
+then read -p got
+else got='no coprocess'
+fi
+[[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'"
+)
+kill $pid 2>/dev/null
+wait
+
+exp='no coprocess'
+
+(
+cop |&
+print $! > $tmp/pid
+)
+pid=$(<$tmp/pid)
+if print -p yo 2>/dev/null
+then read -p got
+else got=$exp
+fi
+[[ $got == $exp ]] || err_exit "subshell coprocess main query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+
+(
+cop |&
+print $! > $tmp/pid
+)
+pid=$(<$tmp/pid)
+(
+if print -p yo 2>/dev/null
+then read -p got
+else got=$exp
+fi
+[[ $got == $exp ]] || err_exit "subshell coprocess subshell query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+)
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/cubetype.sh b/usr/src/lib/libshell/common/tests/cubetype.sh
index f3597d258d..4a718d4a38 100644
--- a/usr/src/lib/libshell/common/tests/cubetype.sh
+++ b/usr/src/lib/libshell/common/tests/cubetype.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -120,7 +120,7 @@ typeset -T Cube_t=(
for ((i=0; i < n; i++))
do
Box_t b=(name=box2)
-[[ ${b.name} == box2 ]] || err_exit "\${b.name} incorrect -- expected box2, got '${b.name}'"
+[[ ${b.name} == box2 ]] || err_exit "\${b.name} incorrect -- expected box2, got '${b.name}'"
(( b.len == 5 )) || err_exit "b.len incorrect for box2 -- expected 5, got '$(( b.len ))'"
(( b.count == 1 )) || err_exit "b.count incorrect -- expected 1, got '$(( b.count ))'"
Cube_t c=(name=cube1)
@@ -134,7 +134,7 @@ Cube_t c=(name=cube1)
(( c.count == 2 )) || err_exit 'c.count != 2'
(( c.count == b.count )) || err_exit 'c.count != b.count'
c.count=0
-Cube_t d=c
+Cube_t d=c
[[ $d == "$c" ]] || err_exit '$d != $c'
eval "Cube_t zzz=$c"
[[ $zzz == "$c" ]] || err_exit '$zzz != $c'
@@ -149,6 +149,7 @@ for ((i=0; i < n; i++))
do
Cube_t cc
cc[2]=(x=2 y=3 name=two colors+=([table]=white) items+=(pencil) z=6)
+[[ ${cc[0].x} == 8 ]] || err_exit 'cc[0].x !=8'
[[ ${cc[2].y} == 3 ]] || err_exit '${cc[2].y} != 3'
(( cc[2].y == 3 )) || err_exit '(( cc[2].y != 3))'
[[ ${cc[2].colors[table]} == white ]] || err_exit '${cc[2].colors[table]} != white'
@@ -162,7 +163,7 @@ unset cc[2].x cc[2].y cc[2].z
(( cc[2].len == cc.len )) || err_exit 'cc[2].len != cc.len'
(( cc[2].count == 6 )) || err_exit 'cc[2].count != 6'
unset cc[2].name cc[2].colors cc[2].items
-[[ $cc == "${cc[2]}" ]] || err_exit '$cc != ${cc[2]}'
+[[ $cc == "${cc[2]}" ]] || err_exit '$cc != ${cc[2]}'
cc.count=0
unset cc
Cube_t -A cc
@@ -181,7 +182,7 @@ unset cc[two].x cc[two].y cc[two].z
(( cc[two].len == cc[one].len )) || err_exit 'cc[two].len != cc[one].len'
(( cc[two].count == 4 )) || err_exit 'cc[two].count != 4'
unset cc[two].name unset cc[two].colors cc[two].items
-[[ ${cc[one]} == "${cc[two]}" ]] || err_exit '${cc[one]} != ${cc[two]}'
+[[ ${cc[one]} == "${cc[two]}" ]] || err_exit '${cc[one]} != ${cc[two]}'
cc[two].count=0
unset cc
Cube_t cc=(
diff --git a/usr/src/lib/libshell/common/tests/enum.sh b/usr/src/lib/libshell/common/tests/enum.sh
index 35d2a27952..1929472bb5 100644
--- a/usr/src/lib/libshell/common/tests/enum.sh
+++ b/usr/src/lib/libshell/common/tests/enum.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -43,8 +43,8 @@ x[2]=green
[[ $x == orange ]] || err_exit '$x is no longer orange'
Color_t -A y
y[foo]=yellow
-[[ ${y[foo]} == yellow ]] || err_exit '${y[foo]} != yellow'
-(( y[foo] == 4 )) || err_exit '(( y[foo] != 4))'
+[[ ${y[foo]} == yellow ]] || err_exit '${y[foo]} != yellow'
+(( y[foo] == 4 )) || err_exit '(( y[foo] != 4))'
unset y
typeset -a [Color_t] z
z[green]=xyz
diff --git a/usr/src/lib/libshell/common/tests/exit.sh b/usr/src/lib/libshell/common/tests/exit.sh
index 01c407bf18..a14b0dcbec 100644
--- a/usr/src/lib/libshell/common/tests/exit.sh
+++ b/usr/src/lib/libshell/common/tests/exit.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -25,6 +25,12 @@ function err_exit
}
alias err_exit='err_exit $LINENO'
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
function abspath
{
base=$(basename $SHELL)
@@ -34,28 +40,20 @@ function abspath
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"
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
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\"
+ v=$(getconf LIBPATH)
+ for v in ${v//,/ }
+ do v=${v#*:}
+ v=${v%%:*}
+ eval [[ \$$v ]] && eval print -n \" \"\$v=\"\$$v\"
done
) \
exec -c -a -ksh ${ABSHELL} -c "exit 1" 1>/dev/null 2>&1
@@ -77,6 +75,6 @@ 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"
$SHELL -c 'builtin -f cmd getconf; getconf --"?-version"; exit 0' >/dev/null 2>&1 || err_exit 'ksh plugin exit failed -- was ksh built with CCFLAGS+=$(CC.EXPORT.DYNAMIC)?'
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/expand.sh b/usr/src/lib/libshell/common/tests/expand.sh
index 5dd46bdd8f..c63e7eb3e2 100644
--- a/usr/src/lib/libshell/common/tests/expand.sh
+++ b/usr/src/lib/libshell/common/tests/expand.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
diff --git a/usr/src/lib/libshell/common/tests/functions.sh b/usr/src/lib/libshell/common/tests/functions.sh
index 0eaa17c688..146b537743 100644
--- a/usr/src/lib/libshell/common/tests/functions.sh
+++ b/usr/src/lib/libshell/common/tests/functions.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -28,12 +28,10 @@ alias err_exit='err_exit $LINENO'
integer Errors=0
Command=${0##*/}
-tmp=/tmp/kshtf$$
-function cleanup
-{
- rm -rf $tmp
-}
-mkdir $tmp || err_exit "mkdir $tmp failed"
+ulimit -c 0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
integer foo=33
bar=bye
@@ -89,11 +87,11 @@ function foobar
{
(return 0)
}
-> $tmp/shtests$$.1
+> $tmp/test1
{
foobar
-if [ -r $tmp/shtests$$.1 ]
-then rm -r $tmp/shtests$$.1
+if [ -r $tmp/test1 ]
+then rm -r $tmp/test1
else err_exit 'return within subshell inside function error'
fi
}
@@ -138,37 +136,36 @@ fun() /bin/echo hello
if [[ $(fun) != hello ]]
then err_exit one line functions not working
fi
-trap cleanup EXIT
-cat > $tmp/script$$ <<-\!
+cat > $tmp/script <<-\!
print -r -- "$1"
!
-chmod +x $tmp/script$$
+chmod +x $tmp/script
function passargs
{
- $tmp/script$$ "$@"
+ $tmp/script "$@"
}
if [[ $(passargs one) != one ]]
then err_exit 'passing args from functions to scripts not working'
fi
-cat > $tmp/script$$ <<-\!
+cat > $tmp/script <<-\!
trap 'exit 0' EXIT
function foo
{
- /tmp > /dev/null 2>&1
+ /tmp > /dev/null 2>&1
}
foo
!
-if ! $tmp/script$$
-then err_exit 'exit trap incorrectly triggered'
+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'
+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'
+$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
+cat > $tmp/script <<- \EOF
foobar()
{
return
@@ -177,8 +174,8 @@ cat > $tmp/script$$ <<- \EOF
foobar
print -r -- "$1"
EOF
-chmod +x $tmp/script$$
-if [[ $( $SHELL $tmp/script$$ arg1 arg2) != arg2 ]]
+chmod +x $tmp/script
+if [[ $( $SHELL $tmp/script arg1 arg2) != arg2 ]]
then err_exit 'arguments not restored by posix functions'
fi
function foo
@@ -212,18 +209,17 @@ 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$$
+unset -f foobar
+cat > $tmp/foobar <<!
+function foobar
{
print foo
}
!
-chmod +x $tmp/foo$$
+chmod +x $tmp/foobar
FPATH=$tmp
-autoload foo$$
-if [[ $(foo$$ 2>/dev/null) != foo ]]
+autoload foobar
+if [[ $(foobar 2>/dev/null) != foo ]]
then err_exit 'autoload not working'
fi
unset -f foobar
@@ -233,14 +229,14 @@ function foobar
return 0
}
( foobar ) 2> /dev/null || err_exit "cannot unset readonly variable in function"
-if $SHELL -n 2> /dev/null <<-!
+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 ...'
+ usage='q pathname ...'
typeset var format=s
while getopts "$usage" var
do case $var in
@@ -296,7 +292,7 @@ then err_exit 'set -e not inherited for posix functions'
fi
trap - ERR
-function myexport
+function myexport
{
nameref var=$1
if (( $# > 1 ))
@@ -309,7 +305,6 @@ function myexport
typeset val
val=$(export | grep "^$1=")
print ${val#"$1="}
-
}
export dgk=base
val=$(myexport dgk fun)
@@ -384,8 +379,26 @@ function closure
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"
+dir=$tmp/dir
+mkdir $dir
+cd $dir || { err_exit "cd $dir failed"; exit 1; }
+
+(
+ function a {
+ print a
+ }
+ function b {
+ print 1
+ a
+ print 2
+ } > /dev/null
+ typeset -ft a b
+ PS4=X
+ b
+) > file 2>&1
+[[ $(<file) == *'Xprint 2'* ]] || err_exit 'function trace disabled by function call'
+rm -f file
+
print 'false' > try
chmod +x try
cat > tst <<- EOF
@@ -400,18 +413,19 @@ 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'
+FPATH=$dir
+print ': This does nothing' > foobar
+chmod +x foobar
+unset -f foobar
+{ foobar; } 2>/dev/null
+got=$?
+exp=126
+if [[ $got != $exp ]]
+then err_exit "function file without function definition processes wrong error -- expected '$exp', got '$got'"
fi
-print 'set a b c' > dotscript
+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
@@ -439,7 +453,7 @@ a()
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'
+cat > $tmp/data1 << '++EOF'
1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
@@ -461,7 +475,7 @@ cat > $tmp/data$$.1 << '++EOF'
19 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
20 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
++EOF
-cat > $tmp/script$$ << '++EOF'
+cat > $tmp/script << '++EOF'
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
@@ -727,10 +741,10 @@ 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'
+cat $tmp/data1 >> $tmp/script
+printf 'M\n}\n\nf\n\n' >> $tmp/script
+$SHELL -c $tmp/script > $tmp/data2
+cmp -s $tmp/data[12] || err_exit 'error with long functions'
v=1
function f
{
@@ -776,7 +790,7 @@ x=$(
integer count=0
function err_f
{
- if ((count++==3))
+ if ((count++==3))
then print failed
else false
fi
@@ -785,7 +799,6 @@ x=$(
false
)
[[ $x == failed ]] && err_exit 'ERR trap executed multiple times'
-trap cleanup EXIT
export environment
typeset global
function f
@@ -819,17 +832,17 @@ function f
}
f local global environment literal positional
$SHELL -c '
- print exit 0 > '$tmp'/script$$
- chmod +x '$tmp'/script$$
+ print exit 0 > '$tmp'/script
+ chmod +x '$tmp'/script
unset var
var=( ident=1 )
function fun
{
- PATH='$tmp' script$$
+ PATH='$tmp' script
}
fun
' || err_exit "compound variable cleanup before script exec failed"
-( $SHELL << \++EOF++
+( $SHELL << \++EOF++
function main
{
typeset key
@@ -921,10 +934,7 @@ unset -f .sh.fun.set
# tests for debug functions
basefile=${.sh.file}
integer baseline
-cleanup
-trap 'rm $tmp' EXIT
-tmp=${TMPDIR:-/tmp}/ksh$$.1
-cat > $tmp << \+++
+cat > $tmp/debug << \+++
: line 1
: line 3
@@ -943,7 +953,7 @@ function _Dbg_print_frame
[[ $arg == DEBUG ]] && ((baseline++))
[[ $line == "$baseline" ]] || err_exit "line number for level 0 is $line not $baseline"
elif ((pos==1))
- then [[ $filename == "$tmp" ]] || err_exit "filename for level 1 is $filename not $tmp"
+ then [[ $filename == "$tmp/debug" ]] || err_exit "filename for level 1 is $filename not $tmp/debug"
[[ $* == 'foo bar' ]] || err_exit "args are '$*', not 'foo bar'"
[[ $line == $arg ]] || err_exit "line number for level 1 is $line not $arg"
else err_exit "level should be 0 or 1 but is $pos"
@@ -963,9 +973,9 @@ function _Dbg_debug_trap_handler
((baseline=LINENO+2))
trap '_Dbg_debug_trap_handler' DEBUG
-. $tmp foo bar
+. $tmp/debug foo bar
trap '' DEBUG
-
+
caller() {
integer .level=.sh.level .max=.sh.level-1
while((--.level>=0))
@@ -978,4 +988,84 @@ bar() { caller;}
set -- $(bar)
[[ $1 == $2 ]] && err_exit ".sh.inline optimization bug"
( $SHELL -c ' function foo { typeset x=$1;print $1;};z=();z=($(foo bar)) ') 2> /dev/null || err_exit 'using a function to set an array in a command sub fails'
+
+{
+got=$(
+s=$(ulimit -s)
+if [[ $s == +([[:digit:]]) ]] && (( s < 16384 ))
+then ulimit -s 16384 2>/dev/null
+fi
+$SHELL << \+++
+f()
+{
+ if (($1>1))
+ then x=$(f $(($1-1))) || exit 1
+ fi
+ return 0
+}
+f 257 && print ok
++++
+)
+} 2>/dev/null
+[[ $got == ok ]] || err_exit 'cannot handle comsub depth > 256 in function'
+
+tmp1=$tmp/job.1
+tmp2=$tmp/job.2
+cat > $tmp1 << +++
+#! $SHELL
+print \$\$
++++
+chmod +x $tmp1
+function foo
+{
+ typeset pid
+ $tmp1 > $tmp2 & pid=$!
+ wait $!
+ [[ $(< $tmp2) == $pid ]] || err_exit 'wrong pid for & job in function'
+}
+foo
+# make sure compiled functions work
+[[ $(tmp=$tmp $SHELL <<- \++++
+ cat > $tmp/functions <<- \EOF
+ function bar
+ {
+ print foo
+ }
+ function foobar
+ {
+ bar
+ }
+ EOF
+ ${SHCOMP:-${SHELL%/*}/shcomp} $tmp/functions > $tmp/foobar
+ rm -f "$tmp/functions"
+ chmod +x $tmp/foobar
+ rm $tmp/!(dir|foobar)
+ FPATH=$tmp
+ PATH=$FPATH:$PATH
+ foobar
+++++
+) == foo ]] > /dev/null || err_exit 'functions compiled with shcomp not working'
+# test for functions in shell having side effects.
+unset -f foo foobar bar
+cd "$tmp"
+FPATH=$PWD
+PATH=$FPATH:$PATH
+cat > foo <<- \EOF
+ function bar
+ {
+ print foobar
+ }
+ function foo
+ {
+ bar
+ }
+EOF
+chmod +x foo
+: $(foo)
+[[ $(typeset +f) == *foo* ]] && err_exit 'function in subshell leaving side effect of function foo'
+unset -f foo bar
+: $(foo)
+[[ $(typeset +f) == *foo* ]] && err_exit 'function in subshell leaving side effects of function foo after reload'
+[[ $(typeset +f) == *bar* ]] && err_exit 'function in subshell leaving side effects of function bar after reload'
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/glob.sh b/usr/src/lib/libshell/common/tests/glob.sh
index 2c3ccd09d3..fa22291c96 100644
--- a/usr/src/lib/libshell/common/tests/glob.sh
+++ b/usr/src/lib/libshell/common/tests/glob.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -24,7 +24,11 @@ function err_exit
}
alias err_exit='err_exit $LINENO'
-integer aware=0 contrary=0 ignorant=0
+Command=${0##*/}
+integer aware=0 contrary=0 errors=0 ignorant=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
function test_glob
{
@@ -84,17 +88,11 @@ function test_case
}
alias test_case='test_case $LINENO'
-Command=${0##*/}
-tmp=/tmp/ksh$$
-integer errors=0
unset undefined
export LC_COLLATE=C
-mkdir $tmp || err_exit "mkdir $tmp failed"
-trap "cd /; rm -rf $tmp" EXIT
-cd $tmp || err_exit "cd $tmp failed"
-rm -rf *
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
touch B b
set -- *
diff --git a/usr/src/lib/libshell/common/tests/grep.sh b/usr/src/lib/libshell/common/tests/grep.sh
index 82c0e13cac..40a80a07a7 100644
--- a/usr/src/lib/libshell/common/tests/grep.sh
+++ b/usr/src/lib/libshell/common/tests/grep.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -28,6 +28,9 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
function grep
{
#
@@ -84,8 +87,7 @@ function grep
let tc # set the return value
}
-trap 'rm -f /tmp/grep$$' EXIT
-cat > /tmp/grep$$ <<\!
+cat > $tmp/grep <<\!
this is a food bar test
to see how many lines find both foo and bar.
Some line contain foo only,
@@ -96,7 +98,7 @@ 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))
+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
index aadc9cdeec..7b3c923bf0 100644
--- a/usr/src/lib/libshell/common/tests/heredoc.sh
+++ b/usr/src/lib/libshell/common/tests/heredoc.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -27,9 +27,12 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
-f=/tmp/here1$$
-g=/tmp/here2$$
-trap "rm -f $f $g" EXIT
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+f=$tmp/here1
+g=$tmp/here2
cat > $f <<!
hello world
!
@@ -143,7 +146,7 @@ abc
EOF) != $'#abc\nabc' ]]
then err_exit 'comments not preserved in here-documents'
fi
-cat > "$f" <<- '!!!!'
+cat > "$f" <<- '!!!!'
builtin cat
: << EOF
$PWD
@@ -173,7 +176,7 @@ chmod 755 "$f"
if [[ $($SHELL "$f") != abc ]]
then err_exit 'here document descritor was closed'
fi
-cat > "$f" <<- '!!!!'
+cat > "$f" <<- '!!!!'
exec 0<&-
foobar()
{
@@ -207,9 +210,9 @@ 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"
+[[ $($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"
+[[ $($SHELL "$f") == $'hello\n\tworld' ]] || err_exit "<<# not working for non-quoted here documents"
[[ $( $SHELL <<- \++++
S=( typeset a )
function S.a.get
@@ -226,4 +229,27 @@ printf $'w=world;cat <<# !!!\n\thello\n\t\t$w\n!!!' > $f
${ g;}
EOF
' 2> /dev/null) == ok ]] || err_exit '${ command;} not working in heredoc'
+script=$f
+{
+for ((i=0; i < 406; i++))
+do print ': 23456789012345678'
+done
+print : 123456789123
+cat <<- \EOF
+eval "$(
+ { cat ; } <<MARKER
+ print hello
+ MARKER
+)"
+EOF
+} > $script
+chmod +x $script
+[[ $($SHELL $script) == hello ]] 2> /dev/null || err_exit 'heredoc embeded in command substitution fails at buffer boundary'
+
+got=$( cat << EOF
+\
+abc
+EOF)
+[[ $got == abc ]] || err_exit 'line continuation at start of buffer not working'
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/io.sh b/usr/src/lib/libshell/common/tests/io.sh
index a8b1b8a030..3468fe9429 100644
--- a/usr/src/lib/libshell/common/tests/io.sh
+++ b/usr/src/lib/libshell/common/tests/io.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -28,29 +28,29 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
unset HISTFILE
function fun
{
- while command exec 3>&1
- do break
+ 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$$
+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
+ 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"
+cd $tmp || { err_exit "cd $tmp failed"; exit ; }
print foo > file1
print bar >> file1
if [[ $(<file1) != $'foo\nbar' ]]
@@ -59,19 +59,55 @@ fi
set -o noclobber
exec 3<> file1
read -u3 line
-if [[ $line != foo ]]
-then err_exit '<> not working right with read'
+exp=foo
+if [[ $line != $exp ]]
+then err_exit "read on <> fd failed -- expected '$exp', got '$line'"
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
+
+FDFS=(
+ ( dir=/proc/self/fd semantics='open' )
+ ( dir=/proc/$$/fd semantics='open' )
+ ( dir=/dev/fd semantics='open|dup' )
+ ( dir=/dev/fd semantics='dup' )
+)
+for ((fdfs=0; fdfs<${#FDFS[@]}-1; fdfs++))
+do [[ -e ${FDFS[fdfs].dir} ]] && { command : > ${FDFS[fdfs].dir}/1; } 2>/dev/null && break
+done
+
+exec 3<> file1
+if command exec 4< ${FDFS[fdfs].dir}/3
+then read -u3 got
+ read -u4 got
+ exp='foo|bar'
+ case $got in
+ foo) semantics='open' ;;
+ bar) semantics='dup' ;;
+ *) semantics='failed' ;;
+ esac
+ [[ $semantics == @(${FDFS[fdfs].semantics}) ]] || err_exit "'4< ${FDFS[fdfs].dir}/3' $semantics semantics instead of ${FDFS[fdfs].semantics} -- expected '$exp', got '$got'"
fi
+
+# 2004-11-25 ancient /dev/fd/N redirection bug fix
+got=$(
+ {
+ print -n 1
+ print -n 2 > ${FDFS[fdfs].dir}/2
+ print -n 3
+ print -n 4 > ${FDFS[fdfs].dir}/2
+ } 2>&1
+)
+exp='1234|4'
+case $got in
+1234) semantics='dup' ;;
+4) semantics='open' ;;
+*) semantics='failed' ;;
+esac
+[[ $semantics == @(${FDFS[fdfs].semantics}) ]] || err_exit "${FDFS[fdfs].dir}/N $semantics semantics instead of ${FDFS[fdfs].semantics} -- expected '$exp', got '$got'"
+
cat > close0 <<\!
exec 0<&-
echo $(./close1)
@@ -91,15 +127,15 @@ cat > close0 <<\!
!
./close0 2> /dev/null || err_exit "multiple exec 4< /dev/null can fail"
$SHELL -c '
- trap "rm -f in$$ out$$" EXIT
+ 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$$
+ done > in
+ > out
+ exec 1<> out
builtin cat
- print -r -- "$(cat in$$)"
- cmp -s in$$ out$$' 2> /dev/null
+ print -r -- "$(<in)"
+ cmp -s in out' 2> /dev/null
[[ $? == 0 ]] || err_exit 'builtin cat truncates files'
cat >| script <<-\!
print hello
@@ -122,7 +158,7 @@ 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"
+exec 3>&- 4>&-
[[ $( {
read -r line;print -r -- "$line"
(
@@ -137,37 +173,26 @@ 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
+cat > $tmp/1 <<- ++EOF++
+ script=$tmp/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"
+ 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
+ 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++
+chmod +x $tmp/1
+[[ $($SHELL $tmp/1) == ok ]] || err_exit "parent i/o causes child script to fail"
+# 2004-12-20 redirection loss bug fix
+cat > $tmp/1 <<- \++EOF++
function a
{
trap 'print ok' EXIT
@@ -175,49 +200,47 @@ cat > /tmp/io$$.1 <<- \++EOF++
}
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 ]]
+chmod +x $tmp/1
+[[ $($tmp/1) == ok ]] || err_exit "trap on EXIT loses last command redirection"
+print > /dev/null {n}> $tmp/1
+[[ ! -s $tmp/1 ]] && newio=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$$
+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"
+ command exec 3<# ((40*8)) || err_exit "absolute seek fails"
read -u3
- [[ $REPLY == +(i) ]] || err_exit "expecting iiii..."
+ [[ $REPLY == +(i) ]] || err_exit "expected iiii..., got $REPLY"
[[ $(3<#) == $(3<# ((CUR)) ) ]] || err_exit '$(3<#)!=$(3<#((CUR)))'
command exec 3<# ((CUR+80))
read -u3
- [[ $REPLY == {39}(l) ]] || err_exit "expecting lll..."
+ [[ $REPLY == {39}(l) ]] || err_exit "expected lll..., got $REPLY"
command exec 3<# ((EOF-80))
read -u3
- [[ $REPLY == +(9) ]] || err_exit "expecting 999...; got $REPLY"
+ [[ $REPLY == +(9) ]] || err_exit "expected 999..., got $REPLY"
command exec 3># ((80))
print -u3 -f "%.39c\n" @
command exec 3># ((80))
read -u3
- [[ $REPLY == +(@) ]] || err_exit "expecting @@@..."
+ [[ $REPLY == +(@) ]] || err_exit "expected @@@..., got $REPLY"
read -u3
- [[ $REPLY == +(d) ]] || err_exit "expecting ddd..."
+ [[ $REPLY == +(d) ]] || err_exit "expected ddd..., got $REPLY"
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))
+ command exec 3<# ((40*62))
read -u3
- [[ $REPLY == +(^) ]] || err_exit "expecting ddd..."
+ [[ $REPLY == +(^) ]] || err_exit "expected ddd..., got $REPLY"
command exec 3<# ((0))
command exec 3<# *jjjj*
read -u3
@@ -227,24 +250,22 @@ then (( $(3<#) == 0 )) || err_exit "not at position 0"
[[ $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*
+ cat $tmp/seek | read -r <# *WWW*
[[ $REPLY == *WWWWW* ]] || err_exit '<# not working for pipes'
- { < /tmp/seek$$ <# ((2358336120)) ;} 2> /dev/null || err_exit 'long seek not working'
-else err_exit "/tmp/seek$$: cannot open for reading"
+ { < $tmp/seek <# ((2358336120)) ;} 2> /dev/null || err_exit 'long seek not working'
+else err_exit "$tmp/seek: cannot open for reading"
fi
command exec 3<&- || 'cannot close 3'
for ((i=0; i < 62; i++))
do printf "%.39c\n" ${x:i:1}
-done > /tmp/seek$$
-if command exec {n}<> /tmp/seek$$
+done > $tmp/seek
+if command exec {n}<> $tmp/seek
then { command exec {n}<#((EOF)) ;} 2> /dev/null || err_exit '{n}<# not working'
if $SHELL -c '{n}</dev/null' 2> /dev/null
then (( $({n}<#) == 40*62)) || err_exit '$({n}<#) not working'
else err_exit 'not able to parse {n}</dev/null'
fi
fi
-trap "" EXIT
-rm -f /tmp/seek$$
$SHELL -ic '
{
print -u2 || exit 2
@@ -258,9 +279,8 @@ $SHELL -ic '
} 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 "{ > $tmp/1 ; date;} >&- 2> /dev/null" > $tmp/2
+[[ -s $tmp/1 || -s $tmp/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'
[[ $(cat <<- \EOF | $SHELL
do_it_all()
@@ -273,12 +293,26 @@ $SHELL -c "$SHELL -c ': 3>&1' 1>&- 2>/dev/null" && err_exit 'closed standard out
EOF) == 'hello world' ]] || err_exit 'invalid readahead on stdin'
$SHELL -c 'exec 3>; /dev/null' 2> /dev/null && err_exit '>; with exec should be an error'
$SHELL -c ': 3>; /dev/null' 2> /dev/null || err_exit '>; not working with at all'
-print hello > /tmp/io.sh$$.1
-if ! $SHELL -c "false >; /tmp/io.sh$$.1" 2> /dev/null
-then [[ $(</tmp/io.sh$$.1) == hello ]] || err_exit '>; not preserving file on failure'
+print hello > $tmp/1
+if ! $SHELL -c "false >; $tmp/1" 2> /dev/null
+then [[ $(<$tmp/1) == hello ]] || err_exit '>; not preserving file on failure'
fi
-if ! $SHELL -c "sed -e 's/hello/hello world/' /tmp/io.sh$$.1" >; /tmp/io.sh$$.1 2> /dev/null
-then [[ $(</tmp/io.sh$$.1) == 'hello world' ]] || err_exit '>; not updating file on success'
+if ! $SHELL -c "sed -e 's/hello/hello world/' $tmp/1" >; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == 'hello world' ]] || err_exit '>; not updating file on success'
+fi
+
+$SHELL -c 'exec 3<>; /dev/null' 2> /dev/null && err_exit '<>; with exec should be an error'
+$SHELL -c ': 3<>; /dev/null' 2> /dev/null || err_exit '<>; not working with at all'
+print $'hello\nworld' > $tmp/1
+if ! $SHELL -c "false <>; $tmp/1" 2> /dev/null
+then [[ $(<$tmp/1) == $'hello\nworld' ]] || err_exit '<>; not preserving file on failure'
+fi
+if ! $SHELL -c "head -1 $tmp/1" <>; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == hello ]] || err_exit '<>; not truncating file on success of head'
+fi
+print $'hello\nworld' > $tmp/1
+if ! $SHELL -c head < $tmp/1 <#((6)) <>; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == world ]] || err_exit '<>; not truncating file on success of behead'
fi
unset y
@@ -303,25 +337,41 @@ abcdefg
[[ $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$$ &
+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$$
+ } 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$$ &
+ 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$$
+ } 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$$
+(
+ print -n 'prompt1: '
+ sleep .1
+ print line2
+ sleep .1
+ print -n 'prompt2: '
+ sleep .1
+) | {
+ read -t2 -n 1000 line1
+ read -t2 -n 1000 line2
+ read -t2 -n 1000 line3
+ read -t2 -n 1000 line4
+}
+[[ $? == 0 ]] && err_exit 'should have time out'
+[[ $line1 == 'prompt1: ' ]] || err_exit "line1 should be 'prompt1: '"
+[[ $line2 == line2 ]] || err_exit "line2 should be line2"
+[[ $line3 == 'prompt2: ' ]] || err_exit "line3 should be 'prompt2: '"
+[[ ! $line4 ]] || err_exit "line4 should be empty"
if $SHELL -c "export LC_ALL=en_US.UTF-8; c=$'\342\202\254'; [[ \${#c} == 1 ]]" 2>/dev/null
then lc_utf8=en_US.UTF-8
@@ -370,4 +420,32 @@ then export LC_ALL=en_US.UTF-8
fi
fi
+exec 3<&2
+file=$tmp/file
+redirect 5>$file 2>&5
+print -u5 -f 'This is a test\n'
+print -u2 OK
+exec 2<&3
+exp=$'This is a test\nOK'
+got=$(< $file)
+[[ $got == $exp ]] || err_exit "output garbled when stderr is duped -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+print 'hello world' > $file
+1<>; $file 1># ((5))
+(( $(wc -c < $file) == 5 )) || err_exit "$file was not truncate to 5 bytes"
+
+$SHELL -c "PS4=':2:'
+ exec 1> $tmp/21.out 2> $tmp/22.out
+ set -x
+ printf ':1:A:'
+ print \$(:)
+ print :1:Z:" 1> $tmp/11.out 2> $tmp/12.out
+[[ -s $tmp/11.out ]] && err_exit "standard output leaked past redirection"
+[[ -s $tmp/12.out ]] && err_exit "standard error leaked past redirection"
+exp=$':1:A:\n:1:Z:'
+got=$(<$tmp/21.out)
+[[ $exp == "$got" ]] || err_exit "standard output garbled -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+exp=$':2:printf :1:A:\n:2::\n:2:print\n:2:print :1:Z:'
+got=$(<$tmp/22.out)
+[[ $exp == "$got" ]] || err_exit "standard error garbled -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/locale.sh b/usr/src/lib/libshell/common/tests/locale.sh
deleted file mode 100644
index ab94722e2d..0000000000
--- a/usr/src/lib/libshell/common/tests/locale.sh
+++ /dev/null
@@ -1,104 +0,0 @@
-########################################################################
-# #
-# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
-# and is licensed under the #
-# Common Public License, Version 1.0 #
-# by AT&T Intellectual Property #
-# #
-# 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
-
-# LC_ALL=debug is an ast specific debug/test locale
-
-if [[ "$(LC_ALL=debug $SHELL <<- \+EOF+
- x=a<1z>b<2yx>c
- print ${#x}
- +EOF+)" != 5
- ]]
-then err_exit '${#x} not working with multibyte locales'
-fi
-
-export LC_ALL=C
-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
-
-export LC_ALL=C
-a=$($SHELL -c '/' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
-b=$($SHELL -c '(LC_ALL=debug / 2>/dev/null); /' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
-[[ "$b" == "$a" ]] || err_exit "locale not restored after subshell -- expected '$a', got '$b'"
-b=$($SHELL -c '(LC_ALL=debug; / 2>/dev/null); /' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
-[[ "$b" == "$a" ]] || err_exit "locale not restored after subshell -- expected '$a', got '$b'"
-
-# test shift-jis \x81\x40 ... \x81\x7E encodings
-# (shift char followed by 7 bit ascii)
-
-typeset -i16 chr
-for lc_all in $(PATH=/bin:/usr/bin locale -a 2>/dev/null | grep -i jis)
-do export LC_ALL=$lc_all
- for ((chr=0x40; chr<=0x7E; chr++))
- do c=${chr#16#}
- for s in \\x81\\x$c \\x$c
- do b="$(printf "$s")"
- eval n=\$\'$s\'
- [[ $b == "$n" ]] || err_exit "LC_ALL=$lc_all printf difference for \"$s\" -- expected '$n', got '$b'"
- u=$(print -- $b)
- q=$(print -- "$b")
- [[ $u == "$q" ]] || err_exit "LC_ALL=$lc_all quoted print difference for \"$s\" -- $b => '$u' vs \"$b\" => '$q'"
- done
- done
-done
-
-# test multibyte value/trace format -- $'\303\274' is UTF-8 u-umlaut
-
-LC_ALL=C
-lc_all=de_DE.UTF-8
-c=$(LC_ALL=C $SHELL -c "printf $':%2s:\n' $'\303\274'")
-u=$(LC_ALL=$lc_all $SHELL -c "printf $':%2s:\n' $'\303\274'" 2>/dev/null)
-if [[ "$c" != "$u" ]]
-then LC_ALL=$lc_all
- x=$'+2+ typeset item.text\
-+3+ item.text=\303\274\
-+4+ print -- \303\274\
-\303\274\
-+5+ eval $\'arr[0]=(\\n\\ttext=\\303\\274\\n)\'
-+2+ arr[0].text=ü\
-+6+ print -- \303\274\
-ü\
-+7+ eval txt=$\'(\\n\\ttext=\\303\\274\\n)\'
-+2+ txt.text=\303\274\
-+8+ print -- \'(\' text=$\'\\303\\274\' \')\'\
-( text=\303\274 )'
- u=$(LC_ALL=$lc_all PS4='+$LINENO+ ' $SHELL -x -c "
- item=(typeset text)
- item.text=$'\303\274'
- print -- \"\${item.text}\"
- eval \"arr[0]=\$item\"
- print -- \"\${arr[0].text}\"
- eval \"txt=\${arr[0]}\"
- print -- \$txt
- " 2>&1)
- [[ "$u" == "$x" ]] || err_exit LC_ALL=$lc_all multibyte value/trace format failed
-fi
-
-exit $Errors
diff --git a/usr/src/lib/libshell/common/tests/nameref.sh b/usr/src/lib/libshell/common/tests/nameref.sh
index 21a672db14..7bb9ec2c91 100644
--- a/usr/src/lib/libshell/common/tests/nameref.sh
+++ b/usr/src/lib/libshell/common/tests/nameref.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -27,6 +27,10 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
function checkref
{
nameref foo=$1 bar=$2
@@ -80,7 +84,7 @@ nameref x=.foo.bar
if [[ ${!x} != .foo.bar ]]
then err_exit "${!x} not working"
fi
-typeset +n x $(typeset +n)
+typeset +n x $(typeset +n)
unset x
nameref x=.foo.bar
function x.set
@@ -96,7 +100,7 @@ fi
if [[ $(typeset -n) != x=.foo.bar ]]
then err_exit "typeset +n doesn't list values of reference variables"
fi
-file=/tmp/shtest$$
+file=$tmp/test
typeset +n foo bar 2> /dev/null
unset foo bar
export bar=foo
@@ -104,7 +108,6 @@ 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
!
@@ -113,7 +116,7 @@ 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"
@@ -127,7 +130,7 @@ then err_exit 'nameref of positional paramters outside of function not working'
fi
unset foo bar
bar=123
-function foobar
+function foobar
{
typeset -n foo=bar
typeset -n foo=bar
@@ -216,7 +219,7 @@ 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'
+[[ ${qs.a} == 3 ]] || err_exit 'function cannot set compound global variable'
unset fun i
foo=(x=hi)
function fun
@@ -297,4 +300,66 @@ vars=(data=())
vars.data._1.a=a.1
vars.data._1.b=b.1
[[ $(a) == 'a.1 b.1' ]] || err_exit 'nameref choosing wrong scope -- '
+typeset +n bam zip foo
+unset bam zip foo
+typeset -A foo
+foo[2]=bar
+typeset -n bam=foo[2]
+typeset -n zip=bam
+[[ $zip == bar ]] || err_exit 'nameref to another nameref to array element fails'
+[[ -R zip ]] || err_exit '[[ -R zip ]] should detect that zip is a reference'
+[[ -R bam ]] || err_exit '[[ -R bam ]] should detect that bam is a reference'
+[[ -R zip ]] || err_exit '[[ -v zip ]] should detect that zip is set'
+[[ -v bam ]] || err_exit '[[ -v bam ]] should detect that bam is set'
+[[ -R 123 ]] && err_exit '[[ -R 123 ]] should detect that 123 is not a reference'
+[[ -v 123 ]] && err_exit '[[ -v 123 ]] should detect that 123 is not set'
+
+unset ref x
+typeset -n ref
+x=3
+function foobar
+{
+ typeset xxx=3
+ ref=xxx
+ return 0
+}
+foobar 2> /dev/null && err_exit 'invalid reference should cause foobar to fail'
+[[ -v ref ]] && err_exit '$ref should be unset'
+ref=x
+[[ $ref == 3 ]] || err_exit "\$ref is $ref, it should be 3"
+function foobar
+{
+ typeset fvar=()
+ typeset -n ref=fvar.foo
+ ref=ok
+ print -r $ref
+}
+[[ $(foobar) == ok ]] 2> /dev/null || err_exit 'nameref in function not creating variable in proper scope'
+function foobar
+{
+ nameref doc=docs
+ nameref bar=doc.num
+ [[ $bar == 2 ]] || err_exit 'nameref scoping error'
+}
+
+docs=(num=2)
+foobar
+
+typeset +n x y
+unset x y
+typeset -A x
+x[a]=(b=c)
+typeset -n y=x[a]
+[[ ${!y.@} == 'x[a].b' ]] || err_exit 'reference to array element not expanded with ${!y.@}'
+
+typeset +n v
+v=()
+k=a.b.c/d
+command typeset -n n=v.${k//['./']/_} 2> /dev/null || err_exit 'patterns with quotes not handled correctly with name reference assignment'
+
+typeset _n sp
+nameref sp=addrsp
+sp[14]=( size=1 )
+[[ -v sp[19] ]] && err_exit '[[ -v sp[19] ]] where sp is a nameref should not be set'
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/options.sh b/usr/src/lib/libshell/common/tests/options.sh
index 07608efa1e..cebb405a27 100644
--- a/usr/src/lib/libshell/common/tests/options.sh
+++ b/usr/src/lib/libshell/common/tests/options.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -29,11 +29,17 @@ Command=${0##*/}
integer Errors=0
unset HISTFILE
+export LC_ALL=C ENV=
+
+ulimit -c 0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
if [[ $( ${SHELL-ksh} -s hello<<-\!
print $1
!
- ) != hello ]]
+ ) != hello ]]
then err_exit "${SHELL-ksh} -s not working"
fi
x=$(
@@ -42,102 +48,118 @@ x=$(
print good
)
if [[ $x != good ]]
-then err_exit 'sh -e not workuing'
+then err_exit 'sh -e not working'
fi
[[ $($SHELL -D -c 'print hi; print $"hello"') == '"hello"' ]] || err_exit 'ksh -D not working'
-tmp=/tmp/ksh$$
-mkdir $tmp
+env=$tmp/.env
+print $'(print -u1 aha) &>/dev/null\n(print -u2 aha) &>/dev/null' > $env
rc=$tmp/.kshrc
print $'PS1=""\nfunction env_hit\n{\n\tprint OK\n}' > $rc
-export ENV='${nosysrc}'$rc
+export ENV=/.$env
+if [[ ! -o privileged ]]
+then
+ got=$($SHELL -E -c : 2>/dev/null)
+ if [[ $g ]]
+ then
+ got=$(printf %q "$got")
+ err_exit "\$ENV file &>/dev/null does not redirect stdout -- expected '', got $got"
+ fi
+ got=$($SHELL -E -c : 2>&1 >/dev/null)
+ if [[ $got != *nonstandard* || $got == *$'\n'* ]]
+ then
+ got=$(printf %q "$got")
+ err_exit "\$ENV file &>/dev/null does not redirect stderr -- expected one diagnostic line, got $got"
+ fi
+fi
+
+export ENV=/.$rc
if [[ -o privileged ]]
then
- [[ $(print env_hit | $SHELL 2>/dev/null) == "OK" ]] &&
+ [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] &&
err_exit 'privileged nointeractive shell reads $ENV file'
- [[ $(print env_hit | $SHELL -E 2>/dev/null) == "OK" ]] &&
+ [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] &&
err_exit 'privileged -E reads $ENV file'
- [[ $(print env_hit | $SHELL +E 2>/dev/null) == "OK" ]] &&
+ [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] &&
err_exit 'privileged +E reads $ENV file'
- [[ $(print env_hit | $SHELL --rc 2>/dev/null) == "OK" ]] &&
+ [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] &&
err_exit 'privileged --rc reads $ENV file'
- [[ $(print env_hit | $SHELL --norc 2>/dev/null) == "OK" ]] &&
+ [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] &&
err_exit 'privileged --norc reads $ENV file'
else
- [[ $(print env_hit | $SHELL 2>/dev/null) == "OK" ]] &&
+ [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] &&
err_exit 'nointeractive shell reads $ENV file'
- [[ $(print env_hit | $SHELL -E 2>/dev/null) == "OK" ]] ||
+ [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] ||
err_exit '-E ignores $ENV file'
- [[ $(print env_hit | $SHELL +E 2>/dev/null) == "OK" ]] &&
+ [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] &&
err_exit '+E reads $ENV file'
- [[ $(print env_hit | $SHELL --rc 2>/dev/null) == "OK" ]] ||
+ [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] ||
err_exit '--rc ignores $ENV file'
- [[ $(print env_hit | $SHELL --norc 2>/dev/null) == "OK" ]] &&
+ [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] &&
err_exit '--norc reads $ENV file'
- [[ $(print env_hit | $SHELL -i 2>/dev/null) == "OK" ]] ||
+ [[ $(print env_hit | $SHELL -i 2>&1) == "OK" ]] ||
err_exit '-i ignores $ENV file'
fi
export ENV=
if [[ -o privileged ]]
then
- [[ $(print env_hit | HOME=$tmp $SHELL 2>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] &&
err_exit '-E ignores empty $ENV'
- [[ $(print env_hit | HOME=$tmp $SHELL +E 2>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] &&
err_exit '--rc ignores empty $ENV'
- [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] ||
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(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>/dev/null) == "OK" ]] ||
+ [[ $(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>/dev/null) == "OK" ]] &&
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
err_exit '--norc reads $HOME/.kshrc file'
fi
-rm -rf $tmp
+rm -rf $tmp/.kshrc
if command set -G 2> /dev/null
-then mkdir /tmp/ksh$$
- cd /tmp/ksh$$
+then cd $tmp
mkdir bar foo
- > bar.c > bam.c
+ > bar.c > bam.c
> bar/foo.c > bar/bam.c
> foo/bam.c
set -- **.c
@@ -157,49 +179,48 @@ then mkdir /tmp/ksh$$
[[ $* == $expected ]] ||
err_exit "-G **/bam.c failed -- expected '$expected', got '$*'"
cd ~-
- rm -rf /tmp/ksh$$
fi
-mkdir /tmp/ksh$$
-cd /tmp/ksh$$
+cd $tmp
t="<$$>.profile.<$$>"
echo "echo '$t'" > .profile
cp $SHELL ./-ksh
if [[ -o privileged ]]
then
- [[ $(HOME=$PWD $SHELL -l </dev/null 2>/dev/null) == *$t* ]] &&
+ [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] &&
err_exit 'privileged -l reads .profile'
- [[ $(HOME=$PWD $SHELL --login </dev/null 2>/dev/null) == *$t* ]] &&
+ [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] &&
err_exit 'privileged --login reads .profile'
- [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>/dev/null) == *$t* ]] &&
+ [[ $(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>/dev/null) == *$t* ]] &&
+ [[ $(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>/dev/null) == *$t* ]] &&
+ [[ $(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>/dev/null) == *$t* ]] &&
+ [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] &&
err_exit 'privileged ./-ksh reads .profile'
- [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>/dev/null) == *$t* ]] &&
+ [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] &&
err_exit 'privileged ./-ksh -p reads .profile'
else
- [[ $(HOME=$PWD $SHELL -l </dev/null 2>/dev/null) == *$t* ]] ||
+ [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] ||
err_exit '-l ignores .profile'
- [[ $(HOME=$PWD $SHELL --login </dev/null 2>/dev/null) == *$t* ]] ||
+ [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] ||
err_exit '--login ignores .profile'
- [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>/dev/null) == *$t* ]] ||
+ [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>&1) == *$t* ]] ||
err_exit '--login-shell ignores .profile'
- [[ $(HOME=$PWD $SHELL --login_shell </dev/null 2>/dev/null) == *$t* ]] ||
+ [[ $(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>/dev/null) == *$t* ]] ||
- err_exit 'exec -a -ksh ksh ignores .profile'
- [[ $(HOME=$PWD ./-ksh -i </dev/null 2>/dev/null) == *$t* ]] ||
+ [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>/dev/null) == *$t* ]] ||
+ err_exit 'exec -a -ksh ksh 2>/dev/null ignores .profile'
+ [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>&1) == *$t* ]] ||
+ err_exit 'exec -a -ksh ksh 2>&1 ignores .profile'
+ [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] ||
err_exit './-ksh ignores .profile'
- [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>/dev/null) == *$t* ]] &&
+ [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] &&
err_exit './-ksh -p does not ignore .profile'
fi
cd ~-
-rm -rf /tmp/ksh$$
-
+rm -rf $tmp/.profile
# { exec interactive login_shell restricted xtrace } in the following test
@@ -333,44 +354,146 @@ set $restore
state=$(set --state)
[[ $state == "set $restore" ]] || err_exit "set --state after restore failed: expected 'set $restore', got '$state'"
-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'
-print hi | (sleep 1;/bin/cat) > /dev/null || err_exit 'pipeline fails with pipefail'
+typeset -a pipeline
+pipeline=(
+ ( nopipefail=0 pipefail=1 command='false|true|true' )
+ ( nopipefail=0 pipefail=1 command='true|false|true' )
+ ( nopipefail=1 pipefail=1 command='true|true|false' )
+ ( nopipefail=1 pipefail=1 command='false|false|false' )
+ ( nopipefail=0 pipefail=0 command='true|true|true' )
+ ( nopipefail=0 pipefail=0 command='print hi|(sleep 1;/bin/cat)>/dev/null' )
+)
+set --nopipefail
+for ((i = 0; i < ${#pipeline[@]}; i++ ))
+do eval ${pipeline[i].command}
+ status=$?
+ expected=${pipeline[i].nopipefail}
+ [[ $status == $expected ]] ||
+ err_exit "--nopipefail '${pipeline[i].command}' exit status $status -- expected $expected"
+done
+ftt=0
+set --pipefail
+for ((i = 0; i < ${#pipeline[@]}; i++ ))
+do eval ${pipeline[i].command}
+ status=$?
+ expected=${pipeline[i].pipefail}
+ if [[ $status != $expected ]]
+ then err_exit "--pipefail '${pipeline[i].command}' exit status $status -- expected $expected"
+ (( i == 0 )) && ftt=1
+ fi
+done
+if (( ! ftt ))
+then exp=10
+ got=$(for((n=1;n<exp;n++))do $SHELL --pipefail -c '(sleep 0.1;false)|true|true' && break; done; print $n)
+ [[ $got == $exp ]] || err_exit "--pipefail -c '(sleep 0.1;false)|true|true' fails with exit status 0 (after $got/$exp iterations)"
+fi
+
+echo=$(whence -p echo)
+for ((i=0; i < 20; i++))
+do if ! x=$(true | $echo 123)
+ then err_exit 'command substitution with wrong exit status with pipefai'
+ break
+ fi
+done
(
set -o pipefail
false | true
(( $? )) || err_exit 'pipe not failing in subshell with pipefail'
) | wc >/dev/null
$SHELL -c 'set -o pipefail; false | $(whence -p true);' && err_exit 'pipefail not returning failure with sh -c'
-[[ $( set -o pipefail
+exp='1212 or 1221'
+got=$(
+ set --pipefail
pipe() { date | cat > /dev/null ;}
print $'1\n2' |
- while read i
- do if pipe /tmp
- then { print enter $i; sleep 2; print leave $i; } &
+ while read i
+ do if pipe $tmp
+ then { print -n $i; sleep 2; print -n $i; } &
fi
done
- wait) == $'enter 1\nenter 2'* ]] || err_exit '& job delayed by pipefail'
-$SHELL -c '[[ $- == *c* ]]' || err_exit 'option c not in $-'
-trap 'rm -f /tmp/.profile' EXIT
-> /tmp/.profile
-for i in i l r s D E a b e f h k n r t u v x B C G H
-do HOME=/tmp ENV= $SHELL -$i 2> /dev/null <<- ++EOF++ || err_exit "option $i not in \$-"
- [[ \$- == *$i* ]] || exit 1
+ wait
+)
+[[ $got == @((12|21)(12|21)) ]] || err_exit "& job delayed by --pipefail, expected '$exp', got '$got'"
+$SHELL -c '[[ $- == *c* ]]' || err_exit 'option c not in $-'
+> $tmp/.profile
+for i in i l r s D E a b e f h k n t u v x B C G H
+do HOME=$tmp ENV= $SHELL -$i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not in \$-"
+ [[ \$- == *$i* ]] || exit 1
++EOF++
done
letters=ilrabefhknuvxBCGE
integer j=0
-for i in interactive login restricted allexport notify errexit \
- noglob trackall keyword noexec nounset verbose xtrace braceexpand \
+for i in interactive login restricted allexport notify errexit \
+ noglob trackall keyword noexec nounset verbose xtrace braceexpand \
noclobber globstar rc
-do HOME=/tmp ENV= $SHELL -o $i 2> /dev/null <<- ++EOF++ || err_exit "option $i not equivalent to ${letters:j:1}"
- [[ \$- == *${letters:j:1}* ]] || exit 1
+do HOME=$tmp ENV= $SHELL -o $i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not equivalent to ${letters:j:1}"
+ [[ \$- == *${letters:j:1}* ]] || exit 1
++EOF++
((j++))
done
+
+export ENV=
+histfile=$tmp/history
+exp=$(HISTFILE=$histfile $SHELL -c $'function foo\n{\ncat\n}\ntype foo')
+for var in HISTSIZE HISTFILE
+do got=$( ( HISTFILE=$histfile $SHELL -ic $'unset '$var$'\nfunction foo\n{\ncat\n}\ntype foo\nexit' ) 2>&1 )
+ got=${got##*': '}
+ [[ $got == "$exp" ]] || err_exit "function definition inside (...) with $var unset fails -- got '$got', expected '$exp'"
+ got=$( { HISTFILE=$histfile $SHELL -ic $'unset '$var$'\nfunction foo\n{\ncat\n}\ntype foo\nexit' ;} 2>&1 )
+ got=${got##*': '}
+ [[ $got == "$exp" ]] || err_exit "function definition inside {...;} with $var unset fails -- got '$got', expected '$exp'"
+done
+( unset HISTFILE; $SHELL -ic "HISTFILE=$histfile" 2>/dev/null ) || err_exit "setting HISTFILE when not in environment fails"
+
+# the next tests loop on all combinations of
+# { SUB PAR CMD ADD }
+
+SUB=(
+ ( BEG='$( ' END=' )' )
+ ( BEG='${ ' END='; }' )
+)
+PAR=(
+ ( BEG='( ' END=' )' )
+ ( BEG='{ ' END='; }' )
+)
+CMD=( command-kill script-kill )
+ADD=( '' '; :' )
+
+cd $tmp
+print $'#!'$SHELL$'\nkill -KILL $$' > command-kill
+print $'kill -KILL $$' > script-kill
+chmod +x command-kill script-kill
+export PATH=.:$PATH
+exp='Killed'
+for ((S=0; S<${#SUB[@]}; S++))
+do for ((P=0; P<${#PAR[@]}; P++))
+ do for ((C=0; C<${#CMD[@]}; C++))
+ do for ((A=0; A<${#ADD[@]}; A++))
+ do cmd="${SUB[S].BEG}${PAR[P].BEG}${CMD[C]}${PAR[P].END} 2>&1${ADD[A]}${SUB[S].END}"
+ eval got="$cmd"
+ got=${got##*': '}
+ got=${got%%'('*}
+ [[ $got == "$exp" ]] || err_exit "$cmd failed -- got '$got', expected '$exp'"
+ done
+ done
+ done
+done
+
+$SHELL 2> /dev/null -c '{; true ;}' || err_exit 'leading ; causes syntax error in brace group'
+$SHELL 2> /dev/null -c '(; true ;)' || err_exit 'leading ; causes syntax error in parenthesis group'
+
+print 'for ((i = 0; i < ${1:-10000}; i++ )); do printf "%.*c\n" 15 x; done' > pipefail
+chmod +x pipefail
+$SHELL --pipefail -c './pipefail 10000 | sed 1q' >/dev/null 2>&1 &
+tst=$!
+{ sleep 4; kill $tst; } 2>/dev/null &
+spy=$!
+wait $tst 2>/dev/null
+status=$?
+if [[ $status == 0 || $(kill -l $status) == PIPE ]]
+then kill $spy 2>/dev/null
+else err_exit "pipefail pipeline bypasses SIGPIPE and hangs"
+fi
+wait
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/path.sh b/usr/src/lib/libshell/common/tests/path.sh
index 2e46e2bd48..edf7621663 100644
--- a/usr/src/lib/libshell/common/tests/path.sh
+++ b/usr/src/lib/libshell/common/tests/path.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -24,12 +24,14 @@ function err_exit
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
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+cd $tmp || exit
type /xxxxxx > out1 2> out2
[[ -s out1 ]] && err_exit 'type should not write on stdout for not found case'
[[ -s out2 ]] || err_exit 'type should write on stderr for not found case'
@@ -69,37 +71,36 @@ PATH=$FPATH:$p
PATH=$p
(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
+cat > bug1 <<- EOF
+ print print ok > $tmp/ok
+ /bin/chmod 755 $tmp/ok
function a
{
- typeset -x PATH=/tmp
- ok$$
+ typeset -x PATH=$tmp
+ ok
}
- path=$PATH
+ path=\$PATH
unset PATH
a
- PATH=$path
+ PATH=\$path
}
EOF
-[[ $($SHELL ./bug1 2> /dev/null) == ok ]] || err_exit "PATH in function not working"
+[[ $($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
+mkdir tdir
+if $SHELL tdir > /dev/null 2>&1
then err_exit 'not an error to run ksh on a directory'
fi
@@ -121,7 +122,7 @@ 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
+ then cmd=notfound$i
break
fi
done
@@ -132,7 +133,7 @@ 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
+do
# print path=$PATH $(whence date)
# print path=$PATH $(whence "$cmd")
date
@@ -155,19 +156,60 @@ fi
status=$?
[[ $status == 126 ]] || err_exit "exit status of non-executable is $status -- 126 expected"
builtin -d rm 2> /dev/null
+chmod=$(whence chmod)
rm=$(whence rm)
d=$(dirname "$rm")
+
+chmod=$(whence chmod)
+
+for cmd in date foo
+do exp="$cmd found"
+ print print $exp > $cmd
+ $chmod +x $cmd
+ got=$($SHELL -c "unset FPATH; PATH=/dev/null; $cmd" 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd as last command should not find ./$cmd with PATH=/dev/null"
+ got=$($SHELL -c "unset FPATH; PATH=/dev/null; $cmd" 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd should not find ./$cmd with PATH=/dev/null"
+ exp=$PWD/./$cmd
+ got=$(unset FPATH; PATH=/dev/null; whence ./$cmd)
+ [[ $got == $exp ]] || err_exit "whence $cmd should find ./$cmd with PATH=/dev/null"
+ exp=$PWD/$cmd
+ got=$(unset FPATH; PATH=/dev/null; whence $PWD/$cmd)
+ [[ $got == $exp ]] || err_exit "whence \$PWD/$cmd should find ./$cmd with PATH=/dev/null"
+done
+
+exp=''
+got=$($SHELL -c "unset FPATH; PATH=/dev/null; whence ./notfound" 2>&1)
+[[ $got == $exp ]] || err_exit "whence ./$cmd failed -- expected '$exp', got '$got'"
+got=$($SHELL -c "unset FPATH; PATH=/dev/null; whence $PWD/notfound" 2>&1)
+[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd failed -- expected '$exp', got '$got'"
+
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'
+for cmd in date foo
+do exp="$cmd found"
+ print print $exp > $cmd
+ $chmod +x $cmd
+ got=$($cmd 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd as last command should not find ./$cmd with PATH=/dev/null"
+ got=$($cmd 2>&1; :)
+ [[ $got == $exp ]] && err_exit "$cmd should not find ./$cmd with PATH=/dev/null"
+ exp=$PWD/./$cmd
+ got=$(whence ./$cmd)
+ [[ $got == $exp ]] || err_exit "whence ./$cmd should find ./$cmd with PATH=/dev/null"
+ exp=$PWD/$cmd
+ got=$(whence $PWD/$cmd)
+ [[ $got == $exp ]] || err_exit "whence \$PWD/$cmd should find ./$cmd with PATH=/dev/null"
+done
+exp=''
+got=$(whence ./notfound)
+[[ $got == $exp ]] || err_exit "whence ./$cmd failed -- expected '$exp', got '$got'"
+got=$(whence $PWD/notfound)
+[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd failed -- expected '$exp', got '$got'"
+
PATH=$d:
-cp "$rm" kshrm$$
-if [[ $(whence kshrm$$) != $PWD/kshrm$$ ]]
+cp "$rm" kshrm
+if [[ $(whence kshrm) != $PWD/kshrm ]]
then err_exit 'trailing : in pathname not working'
fi
cp "$rm" rm
@@ -196,7 +238,7 @@ then PATH=
then err_exit 'unsetting path not working'
fi
fi
-PATH=/dev:/tmp/ksh$$
+PATH=/dev:$tmp
x=$(whence rm)
typeset foo=$(PATH=/xyz:/abc :)
y=$(whence rm)
@@ -212,11 +254,11 @@ 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=$($SHELL -c $'trap \'print $?\' EXIT;/xxx/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=$($SHELL -c $'trap \'print $?\' ERR;/xxx/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"
@@ -231,7 +273,7 @@ getconf UNIVERSE - att # override sticky default 'UNIVERSE = foo'
PATH=$path
-scr=/tmp/ksh$$/foo
+scr=$tmp/script
exp=126
: > $scr
diff --git a/usr/src/lib/libshell/common/tests/pointtype.sh b/usr/src/lib/libshell/common/tests/pointtype.sh
index 25b9f5fbc5..28b60c499c 100644
--- a/usr/src/lib/libshell/common/tests/pointtype.sh
+++ b/usr/src/lib/libshell/common/tests/pointtype.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
diff --git a/usr/src/lib/libshell/common/tests/quoting.sh b/usr/src/lib/libshell/common/tests/quoting.sh
index b15739da08..a1df26a230 100644
--- a/usr/src/lib/libshell/common/tests/quoting.sh
+++ b/usr/src/lib/libshell/common/tests/quoting.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -212,12 +212,12 @@ fi
foo=bar
bar=$(print -r -- ${foo+\\n\ })
if [[ $bar != '\n ' ]]
-then err_exit '${foo+\\n\ } expansion error'
+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'
+then err_exit '${foo+\\n\ $bar} expansion error with bar unset'
fi
x='\\(..\\)|&\|\|\\&\\|'
if [[ $(print -r -- $x) != "$x" ]]
@@ -326,7 +326,7 @@ string='&foo'
{
x=x
x=${x:-`id | sed 's/^[^(]*(\([^)]*\)).*/\1/'`}
-} 2> /dev/null || err_exit 'skipping over `` failed'
+} 2> /dev/null || err_exit 'skipping over `` failed'
[[ $x == x ]] || err_exit 'assignment ${x:=`...`} failed'
[[ $($SHELL -c 'print a[') == 'a[' ]] || err_exit "unbalanced '[' in command arg fails"
$SHELL -c $'false && (( `wc -l /dev/null | nawk \'{print $1}\'` > 2 )) && true;:' 2> /dev/null || err_exit 'syntax error with ` in arithmetic expression'
@@ -334,4 +334,9 @@ $SHELL -c $'false && (( `wc -l /dev/null | nawk \'{print $1}\'` > 2 )) && true;:
varname=foobarx
x=`print '"\$'${varname}'"'`
[[ $x == '"$foobarx"' ]] || err_exit $'\\$\' not handled correctly inside ``'
+
+copy1=5 copynum=1
+foo="`eval echo "$"{copy$copynum"-0}"`"
+[[ $foo == "$copy1" ]] || err_exit '$"..." not being ignored inside ``'
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/quoting2.sh b/usr/src/lib/libshell/common/tests/quoting2.sh
index 334ed40e7c..dab0992f6b 100644
--- a/usr/src/lib/libshell/common/tests/quoting2.sh
+++ b/usr/src/lib/libshell/common/tests/quoting2.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -197,11 +197,13 @@ foo=foo
[[ "$" == '$' ]] || err_exit '"$" != $'
[[ "${foo}$" == 'foo$' ]] || err_exit 'foo=foo;"${foo}$" != foo$'
[[ "${foo}${foo}$" == 'foofoo$' ]] || err_exit 'foo=foo;"${foo}${foo}$" != foofoo$'
-foo='$ '
+foo='$ '
[[ "$foo" == ~(Elr)(\\\$|#)\ ]] || err_exit $'\'$ \' not matching RE \\\\\\$|#\''
-[[ "$foo" == ~(Elr)('\$'|#)\ ]] || err_exit $'\'$ \' not matching RE \'\\$\'|#\''
+[[ "$foo" == ~(Elr)('\$'|#)\ ]] || err_exit $'\'$ \' not matching RE \'\\$\'|#\''
foo='# '
-[[ "$foo" == ~(Elr)(\\\$|#)\ ]] || err_exit $'\'# \' not matching RE \\'\$|#\''
+[[ "$foo" == ~(Elr)(\\\$|#)\ ]] || err_exit $'\'# \' not matching RE \\'\$|#\''
[[ "$foo" == ~(Elr)('\$'|#)\ ]] || err_exit $'\'# \' not matching RE \'\\$\'|#\''
[[ '\$' == '\$'* ]] || err_exit $'\'\\$\' not matching \'\\$\'*'
+[[ a+a == ~(E)a\+a ]] || err_exit '~(E)a\+a not matching a+a'
+[[ a+a =~ a\+a ]] || err_exit 'RE a\+a not matching a+a'
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/recttype.sh b/usr/src/lib/libshell/common/tests/recttype.sh
index 8fe1f3d4ff..b2bca80f50 100644
--- a/usr/src/lib/libshell/common/tests/recttype.sh
+++ b/usr/src/lib/libshell/common/tests/recttype.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
diff --git a/usr/src/lib/libshell/common/tests/restricted.sh b/usr/src/lib/libshell/common/tests/restricted.sh
index 9cc28c7303..eca93ce6f2 100644
--- a/usr/src/lib/libshell/common/tests/restricted.sh
+++ b/usr/src/lib/libshell/common/tests/restricted.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -25,11 +25,13 @@ function err_exit
}
alias err_exit='err_exit $LINENO'
-# test restricted shell
Command=${0##*/}
integer Errors=0
-mkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed"
-trap "cd /; rm -rf /tmp/ksh$$" EXIT
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test restricted shell
pwd=$PWD
case $SHELL in
/*) ;;
@@ -40,14 +42,14 @@ function check_restricted
{
rm -f out
rksh -c "$@" 2> out > /dev/null
- grep restricted out > /dev/null 2>&1
+ grep restricted out > /dev/null 2>&1
}
[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL
-cd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed"
+cd $tmp || err_exit "cd $tmp failed"
ln -s $SHELL rksh
PATH=$PWD:$PATH
-rksh -c '[[ -o restricted ]]' || err_exit 'restricted option not set'
+rksh -c '[[ -o restricted ]]' || err_exit 'restricted option not set'
[[ $(rksh -c 'print hello') == hello ]] || err_exit 'unable to run print'
check_restricted /bin/echo || err_exit '/bin/echo not resticted'
check_restricted ./echo || err_exit './echo not resticted'
@@ -74,4 +76,7 @@ print hello
!
! check_restricted 'script;:' || err_exit 'script with #! pathname should run in restricted mode'
! check_restricted 'script' || err_exit 'script with #! pathname should run in restricted mode even if last command in script'
+for i in PATH ENV FPATH
+do check_restricted "function foo { typeset $i=foobar;};foo" || err_exit "$i can be changed in function by using typeset"
+done
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/return.sh b/usr/src/lib/libshell/common/tests/return.sh
index ac9d2761c0..c9bbf0f33c 100644
--- a/usr/src/lib/libshell/common/tests/return.sh
+++ b/usr/src/lib/libshell/common/tests/return.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -26,14 +26,17 @@ function err_exit
let Errors+=1
}
alias err_exit='err_exit $LINENO'
+
Command=${0##*/}
integer Errors=0
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
unset HISTFILE
foo=NOVAL bar=NOVAL
-file=/tmp/shtest$$
-trap "rm -f $file" EXIT INT
+file=$tmp/test
function foo
{
typeset foo=NOEXIT
@@ -125,7 +128,7 @@ then err_exit "return in script is $ret should be 3"
fi
cat > $file <<!
: line 1
-# next line should fail and cause an exit
+# next line should fail and cause an exit
: > /
exit 4
!
diff --git a/usr/src/lib/libshell/common/tests/select.sh b/usr/src/lib/libshell/common/tests/select.sh
index 578fca2e11..2728f85a40 100644
--- a/usr/src/lib/libshell/common/tests/select.sh
+++ b/usr/src/lib/libshell/common/tests/select.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -27,10 +27,13 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
-trap "rm -f /tmp/Sh$$*" EXIT
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
PS3='ABC '
-cat > /tmp/Sh$$.1 <<\!
+cat > $tmp/1 <<\!
1) foo
2) bar
3) bam
@@ -57,7 +60,7 @@ do case $i in
( set -u; : $i ) || err_exit "select: i not set to null" 2>&3
break;;
esac
-done 3>&2 2> /tmp/Sh$$.2 <<!
+done 3>&2 2> $tmp/2 <<!
foo
!
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/shtests b/usr/src/lib/libshell/common/tests/shtests
index 63b8db0462..37a36c29ef 100644
--- a/usr/src/lib/libshell/common/tests/shtests
+++ b/usr/src/lib/libshell/common/tests/shtests
@@ -1,13 +1,15 @@
# This program runs ksh regression tests
# shtests [ name=value ... ] [ --all | --compile ] [ --time ] [ a.sh b.sh ... ]
-unset DISPLAY ENV FIGNORE
+timesensitive='*@(options|sigchld|subshell).sh'
+
+unset DISPLAY ENV FIGNORE HISTFILE
LANG=C
LC_ALL=C
compile=1
script=1
time=1
-vmdebug=1
+vmdebug=a
while :
do case $1 in
-a|--a*)compile=2
@@ -38,9 +40,11 @@ do case $1 in
done
if [[ ! $vmdebug ]]
then unset VMDEBUG
-elif [[ ! $VMDEBUG ]]
-then export VMDEBUG=a
+elif [[ $VMDEBUG ]]
+then vmdebug=$VMDEBUG
+else export VMDEBUG=$vmdebug
fi
+[[ $VMDEBUG ]] || timesensitive=.
export LANG LC_ALL PATH PWD SHELL
PWD=`pwd`
SHELL=${SHELL-ksh}
@@ -65,9 +69,8 @@ fi
if [[ $compile ]]
then SHCOMP=${SHCOMP:-shcomp}
if whence $SHCOMP > /dev/null
- then tmp=/tmp/ksh-$$
- trap 'rm -rf $tmp' EXIT
- mkdir $tmp || exit
+ then tmp=$(mktemp -dt) || { echo mktemp -dt failed >&2; exit 1; }
+ trap "cd /; rm -rf $tmp" EXIT
elif [[ $compile != 1 ]]
then echo $0: --compile: $SHCOMP not found >&2
exit 1
@@ -88,6 +91,9 @@ do t=$(grep -c err_exit $i)
E=error
if [[ $script ]]
then echo test $i begins ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"}
+ if [[ $i == $timesensitive ]]
+ then unset VMDEBUG
+ fi
if $SHELL $i
then echo test $i passed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} "[ $t $T 0 ${E}s ]"
else e=$?
@@ -100,6 +106,9 @@ do t=$(grep -c err_exit $i)
fi
echo test $i failed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T $e $E ]"
fi
+ if [[ $i == $timesensitive ]]
+ then export VMDEBUG=$vmdebug
+ fi
fi
done
if [[ $compile ]]
@@ -114,7 +123,10 @@ then for i in ${*-*.sh}
echo test $o begins ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"}
E=error
if $SHCOMP $i > $tmp/$o
- then if $SHELL $tmp/$o
+ then if [[ $i == $timesensitive ]]
+ then unset VMDEBUG
+ fi
+ if $SHELL $tmp/$o
then echo test $o passed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} "[ $t $T 0 ${E}s ]"
else e=$?
if (( e > 256 ))
@@ -126,6 +138,9 @@ then for i in ${*-*.sh}
fi
echo test $o failed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T $e $E ]"
fi
+ if [[ $i == $timesensitive ]]
+ then export VMDEBUG=$vmdebug
+ fi
else e=$?
t=1
T=test
diff --git a/usr/src/lib/libshell/common/tests/sigchld.sh b/usr/src/lib/libshell/common/tests/sigchld.sh
index 018eb9fbc0..0b2bf8e03f 100644
--- a/usr/src/lib/libshell/common/tests/sigchld.sh
+++ b/usr/src/lib/libshell/common/tests/sigchld.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -59,7 +59,55 @@ print foreground=$foreground background=$background
eval $s
-(( foreground == FOREGROUND )) || err_exit "expected $FOREGROUND foreground -- got $foreground (DELAY=$DELAY)"
-(( background == BACKGROUND )) || err_exit "expected $BACKGROUND background -- got $background (DELAY=$DELAY)"
+(( foreground == FOREGROUND )) || err_exit "expected '$FOREGROUND foreground' -- got '$foreground' (DELAY=$DELAY)"
+(( background == BACKGROUND )) || err_exit "expected '$BACKGROUND background' -- got '$background' (DELAY=$DELAY)"
+
+set --noerrexit
+
+if [[ ${.sh.version} == Version?*([[:upper:]])J* ]]
+then
+
+ jobmax=4
+ got=$($SHELL -c '
+ JOBMAX='$jobmax' JOBCOUNT=$(('$jobmax'*2))
+ integer running=0 maxrunning=0
+ trap "((running--))" CHLD
+ for ((i=0; i<JOBCOUNT; i++))
+ do sleep 1 &
+ if ((++running > maxrunning))
+ then ((maxrunning=running))
+ fi
+ done
+ wait
+ print running=$running maxrunning=$maxrunning
+ ')
+ exp='running=0 maxrunning='$jobmax
+ [[ $got == $exp ]] || err_exit "SIGCHLD trap queueing failed -- expected '$exp', got '$got'"
+
+ got=$($SHELL -c '
+ typeset -A proc
+
+ trap "
+ print \${proc[\$!].name} \${proc[\$!].status} \$?
+ unset proc[\$!]
+ " CHLD
+
+ { sleep 3; print a; exit 1; } &
+ proc[$!]=( name=a status=1 )
+
+ { sleep 2; print b; exit 2; } &
+ proc[$!]=( name=b status=2 )
+
+ { sleep 1; print c; exit 3; } &
+ proc[$!]=( name=c status=3 )
+
+ while (( ${#proc[@]} ))
+ do sleep -s
+ done
+ ')
+ exp='c\nc 3 3\nb\nb 2 2\na\na 1 1'
+ [[ $got == $exp ]] || err_exit "SIGCHLD trap queueing failed -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+
+fi
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/signal.sh b/usr/src/lib/libshell/common/tests/signal.sh
index 12b06d6fca..bab844fc4d 100644
--- a/usr/src/lib/libshell/common/tests/signal.sh
+++ b/usr/src/lib/libshell/common/tests/signal.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -28,14 +28,39 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
-mkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed"
-trap 'cd /; rm -rf /tmp/ksh$$' EXIT
-cd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed"
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+cd $tmp || err_exit "cd $tmp failed"
+
+(
+ set --pipefail
+ {
+ $SHELL 2> out2 <<- \EOF
+ g=false
+ trap 'print -u2 PIPED; $g && exit 0;g=true' PIPE
+ while :
+ do print hello
+ done
+ EOF
+ } | head > /dev/null
+ (( $? == 0)) || err_exit "SIGPIPE with wrong error code $?"
+ [[ $(<out2) == $'PIPED\nPIPED' ]] || err_exit 'SIGPIPE output on standard error is not correct'
+) &
+cop=$!
+{ sleep 4; kill $cop; } 2>/dev/null &
+spy=$!
+if wait $cop 2>/dev/null
+then kill $spy 2>/dev/null
+else err_exit "pipe with --pipefail PIPE trap hangs"
+fi
+wait
+rm -f out2
[[ $( trap 'print -n got_child' SIGCHLD
sleep 2 &
for ((i=0; i < 4; i++))
- do sleep .9
+ do sleep .75
print -n $i
done) == 01got_child23 ]] || err_exit 'SIGCHLD not working'
@@ -55,7 +80,8 @@ cat > tst <<'!'
#
# d call next script directly, otherwise via $SHELL -c
# t trap, echo, and kill self on SIGINT, otherwise x or SIGINT default if no x
-# x trap, echo on SIGINT, and exit 0, otherwise SIGINT default
+# x trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit, otherwise SIGINT default
+# z trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit 0, otherwise SIGINT default
#
# Usage: tst [-v] [-options] shell-to-test ...
@@ -71,7 +97,7 @@ set -o monitor
function gen
{
typeset o t x d
- for x in - x
+ for x in - x z
do case $x in
[$1]) for t in - t
do case $t in
@@ -153,6 +179,11 @@ sleep 2
!
cat > tst-2 <<'!'
case $1 in
+*z*) trap '
+ echo 2-intr
+ exit 0
+ ' INT
+ ;;
*x*) trap '
echo 2-intr
exit
@@ -176,7 +207,7 @@ printf '2-%04d\n' $status
!
cat > tst-3 <<'!'
case $1 in
-*x*) trap '
+*[xz]*) trap '
sleep 2
echo 3-intr
exit 0
@@ -206,10 +237,14 @@ expected[---]="3-intr"
expected[--d]="3-intr"
expected[-t-]="3-intr 2-intr 1-intr 1-0258"
expected[-td]="3-intr 2-intr 1-intr 1-0258"
-expected[x--]="3-intr 2-intr 1-0000"
-expected[x-d]="3-intr 2-intr 1-0000"
-expected[xt-]="3-intr 2-intr 1-intr 1-0000"
-expected[xtd]="3-intr 2-intr 1-intr 1-0000"
+expected[x--]="3-intr 2-intr"
+expected[x-d]="3-intr 2-intr"
+expected[xt-]="3-intr 2-intr 1-intr 1-0258"
+expected[xtd]="3-intr 2-intr 1-intr 1-0258"
+expected[z--]="3-intr 2-intr 1-0000"
+expected[z-d]="3-intr 2-intr 1-0000"
+expected[zt-]="3-intr 2-intr 1-intr 1-0000"
+expected[ztd]="3-intr 2-intr 1-intr 1-0000"
tst $SHELL > tst.got
@@ -218,9 +253,71 @@ do [[ $out == ${expected[$ops]} ]] || err_exit "interrupt $ops test failed -- ex
done < tst.got
float s=$SECONDS
-[[ $($SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell ignoring signal does not send signal to parent'
+[[ $($SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell ignoring signal does not send signal to parent'
(( (SECONDS-s) < 4 )) && err_exit 'parent does not wait for child to complete before handling signal'
((s = SECONDS))
-[[ $($SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "exit" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell catching signal does not send signal to parent'
+[[ $($SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "exit" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell catching signal does not send signal to parent'
(( SECONDS-s < 4 )) && err_exit 'parent completes early'
+
+unset n s t
+for s in $(kill -l)
+do if ! n=$(kill -l $s 2>/dev/null)
+ then err_exit "'kill -l $s' failed"
+ continue
+ fi
+ if ! t=$(kill -l $n 2>/dev/null)
+ then err_exit "'kill -l $n' failed"
+ continue
+ fi
+ if [[ $s == ?(SIG)$t ]]
+ then continue
+ fi
+ if ! m=$(kill -l $t 2>/dev/null)
+ then err_exit "'kill -l $t' failed"
+ continue
+ fi
+ if [[ $m == $n ]]
+ then continue
+ fi
+ err_exit "'kill -l $s' => $n, 'kill -l $n' => $t, kill -l $t => $m -- expected $n"
+done
+yes=$(whence -p yes)
+[[ $yes ]] && for exp in TERM VTALRM PIPE
+do { $SHELL <<- EOF
+ foo() { return 0; }
+ trap foo EXIT
+ { sleep 2; kill -$exp \$\$; sleep 3; kill -0 \$\$ && kill -KILL \$\$; } &
+ $yes | while read yes; do
+ (/bin/date; sleep .1)
+ done > /dev/null
+ EOF
+ } 2>> /dev/null
+ got=$(kill -l $?)
+ [[ $exp == $got ]] || err_exit "kill -$exp \$\$ failed, required termination by signal '$got'"
+done
+
+SECONDS=0
+$SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done;exit 3" EXIT; (sleep 5);print finished' > $tmp/sig
+(( $?==3)) || err_exit "wrong exit status expecting 3 got $?"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "wrong result - execting done got $x"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expecting around 2"
+
+SECONDS=0
+{ $SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done;exit" EXIT; (sleep 5);print finished' > $tmp/sig ;} 2> /dev/null
+[[ $(kill -l $?) == TERM ]] || err_exit "wrong exit status expecting TERM got $(kill -l $?)"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "wrong result - execting done got $x"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expecting around 2"
+
+SECONDS=0
+x=$($SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done;exit 3" EXIT; (sleep 5);print finished')
+(( $?==3)) || err_exit "wrong exit status expecting 3 got $?"
+[[ $x == done ]] || err_exit "wrong result - execting done got $x"
+(( SECONDS < 4 )) && err_exit "took $SECONDS seconds, expecting around 5"
+
+trap '' SIGBUS
+[[ $($SHELL -c 'trap date SIGBUS;trap -p SIGBUS') ]] && err_exit 'SIGBUS should not have a trap'
+trap -- - SIGBUS
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/statics.sh b/usr/src/lib/libshell/common/tests/statics.sh
index d6af9c7c91..21175c08db 100644
--- a/usr/src/lib/libshell/common/tests/statics.sh
+++ b/usr/src/lib/libshell/common/tests/statics.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -30,9 +30,9 @@ function testfunc
typeset cmd="$2"
typeset expected_output="$3"
typeset output
-
+
output="$($SHELL -c "${cmd}" 2>&1 )"
-
+
[[ "${output}" != "${expected_output}" ]] && err_exit2 ${line_number} "${output} != ${expected_output}"
}
alias testfunc='testfunc $LINENO'
@@ -60,9 +60,9 @@ testfunc '(function l { float -S x=0.5 ; (( x+=.5 )) ; $1 && print "$x" ; } ;
function l
{
typeset -S s=( a=0 b=0 )
-
+
(( s.a++, s.b++ ))
-
+
$1 && printf 'a=%d, b=%d\n' s.a s.b
}
l false ; l false ; l true
@@ -75,9 +75,9 @@ got=$(
function ar
{
typeset -a -S s=( "hello" )
-
+
s+=( "an element" )
-
+
$1 && { printf '%s' "${s[@]}" ; printf '\n' ; }
}
ar false ; ar false ; ar true
diff --git a/usr/src/lib/libshell/common/tests/subshell.sh b/usr/src/lib/libshell/common/tests/subshell.sh
index 985aba6eaa..bc63bde995 100644
--- a/usr/src/lib/libshell/common/tests/subshell.sh
+++ b/usr/src/lib/libshell/common/tests/subshell.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -24,9 +24,15 @@ function err_exit
(( Errors+=1 ))
}
alias err_exit='err_exit $LINENO'
+
Command=${0##*/}
integer Errors=0 Error_fd=2
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+bincat=$(PATH=$(getconf PATH) whence -p cat)
+
z=()
z.foo=( [one]=hello [two]=(x=3 y=4) [three]=hi)
z.bar[0]=hello
@@ -70,7 +76,7 @@ false
[[ ${z.bar[1]} == yes ]] || err_exit 'index array assignment to compound variable in subshell not working'
)
[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment'
-
+
x=(
foo=( qqq=abc rrr=def)
bar=( zzz=no rst=fed)
@@ -97,8 +103,6 @@ while whence $TEST_notfound >/dev/null 2>&1
do TEST_notfound=notfound-$RANDOM
done
-tmp=/tmp/kshsubsh$$
-trap "rm -f $tmp" EXIT
integer BS=1024 nb=64 ss=60 bs no
for bs in $BS 1
do $SHELL -c '
@@ -109,8 +113,8 @@ do $SHELL -c '
set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs')
print ${#1}
kill $!
- ' > $tmp 2>/dev/null
- no=$(<$tmp)
+ ' > $tmp/sub 2>/dev/null
+ no=$(<$tmp/sub)
(( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs -- expected $((BS*nb)), got ${no:-0}"
done
# this time with redirection on the trailing command
@@ -124,8 +128,8 @@ do $SHELL -c '
set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs' 2>/dev/null)
print ${#1}
kill $!
- ' > $tmp 2>/dev/null
- no=$(<$tmp)
+ ' > $tmp/sub 2>/dev/null
+ no=$(<$tmp/sub)
(( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs and trailing redirection -- expected $((BS*nb)), got ${no:-0}"
done
@@ -220,4 +224,230 @@ do for TEST_exec in '' 'exec'
done
done
+$SHELL -c '( autoload xxxxx);print -n' || err_exit 'autoloaded functions in subshells can cause failure'
+foo=$($SHELL <<- ++EOF++
+ (trap 'print bar' EXIT;print -n foo)
+ ++EOF++
+)
+[[ $foo == foobar ]] || err_exit 'trap on exit when last commands is subshell is not triggered'
+
+err=$(
+ $SHELL 2>&1 <<- \EOF
+ date=$(whence -p date)
+ function foo
+ {
+ x=$( $date > /dev/null 2>&1 ;:)
+ }
+ # consume almost all fds to push the test to the fd limit #
+ integer max=$(ulimit --nofile)
+ (( max -= 6 ))
+ for ((i=20; i < max; i++))
+ do exec {i}>&1
+ done
+ for ((i=0; i < 20; i++))
+ do y=$(foo)
+ done
+ EOF
+) || {
+ err=${err%%$'\n'*}
+ err=${err#*:}
+ err=${err##[[:space:]]}
+ err_exit "nested command substitution with redirections failed -- $err"
+}
+
+exp=0
+$SHELL -c $'
+ function foobar
+ {
+ print "hello world"
+ }
+ [[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]]
+ exit '$exp$'
+'
+got=$?
+[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'"
+exp=ok
+got=$($SHELL -c $'
+ function foobar
+ {
+ print "hello world"
+ }
+ [[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]]
+ print '$exp$'
+')
+[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'"
+
+# command substitution variations #
+set -- \
+ '$(' ')' \
+ '${ ' '; }' \
+ '$(ulimit -c 0; ' ')' \
+ '$( (' ') )' \
+ '${ (' '); }' \
+ '`' '`' \
+ '`(' ')`' \
+ '`ulimit -c 0; ' '`' \
+ # end of table #
+exp=ok
+testcase[1]='
+ if %sexpr "NOMATCH" : ".*Z" >/dev/null%s
+ then print error
+ else print ok
+ fi
+ exit %s
+'
+testcase[2]='
+ function bar
+ {
+ pipeout=%1$sprintf Ok | tr O o%2$s
+ print $pipeout
+ return 0
+ }
+ foo=%1$sbar%2$s || foo="exit status $?"
+ print $foo
+ exit %3$s
+'
+while (( $# >= 2 ))
+do for ((TEST=1; TEST<=${#testcase[@]}; TEST++))
+ do body=${testcase[TEST]}
+ for code in 0 2
+ do got=${ printf "$body" "$1" "$2" "$code" | $SHELL 2>&1 }
+ status=$?
+ if (( status != code ))
+ then err_exit "test $TEST '$1...$2 exit $code' failed -- exit status $status, expected $code"
+ elif [[ $got != $exp ]]
+ then err_exit "test $TEST '$1...$2 exit $code' failed -- got '$got', expected '$exp'"
+ fi
+ done
+ done
+ shift 2
+done
+
+# the next tests loop on all combinations of
+# { SUB CAT INS TST APP } X { file-sizes }
+# where the file size starts at 1Ki and doubles up to and including 1Mi
+#
+# the tests and timeouts are done in async subshells to prevent
+# the test harness from hanging
+
+SUB=(
+ ( BEG='$( ' END=' )' )
+ ( BEG='${ ' END='; }' )
+)
+CAT=( cat $bincat )
+INS=( "" "builtin cat; " "builtin -d cat $bincat; " ": > /dev/null; " )
+APP=( "" "; :" )
+TST=(
+ ( CMD='print foo | $cat' EXP=3 )
+ ( CMD='$cat < $tmp/lin' )
+ ( CMD='cat $tmp/lin | $cat' )
+ ( CMD='read v < $tmp/buf; print $v' LIM=4*1024 )
+ ( CMD='cat $tmp/buf | read v; print $v' LIM=4*1024 )
+)
+
+command exec 3<> /dev/null
+if cat /dev/fd/3 >/dev/null 2>&1
+then T=${#TST[@]}
+ TST[T].CMD='$cat <(print foo)'
+ TST[T].EXP=3
+fi
+
+# prime the two data files to 512 bytes each
+# $tmp/lin has newlines every 16 bytes and $tmp/buf has no newlines
+# the outer loop doubles the file size at top
+
+buf=$'1234567890abcdef'
+lin=$'\n1234567890abcde'
+for ((i=0; i<5; i++))
+do buf=$buf$buf
+ lin=$lin$lin
+done
+print -n "$buf" > $tmp/buf
+print -n "$lin" > $tmp/lin
+
+unset SKIP
+for ((n=1024; n<=1024*1024; n*=2))
+do cat $tmp/buf $tmp/buf > $tmp/tmp
+ mv $tmp/tmp $tmp/buf
+ cat $tmp/lin $tmp/lin > $tmp/tmp
+ mv $tmp/tmp $tmp/lin
+ for ((S=0; S<${#SUB[@]}; S++))
+ do for ((C=0; C<${#CAT[@]}; C++))
+ do cat=${CAT[C]}
+ for ((I=0; I<${#INS[@]}; I++))
+ do for ((A=0; A<${#APP[@]}; A++))
+ do for ((T=0; T<${#TST[@]}; T++))
+ do #undent...#
+
+ if [[ ! ${SKIP[S][C][I][A][T]} ]]
+ then eval "{ x=${SUB[S].BEG}${INS[I]}${TST[T].CMD}${APP[A]}${SUB[S].END}; print \${#x}; } >\$tmp/out &"
+ m=$!
+ { sleep 4; kill -9 $m; } &
+ k=$!
+ wait $m
+ h=$?
+ kill -9 $k
+ wait $k
+ got=$(<$tmp/out)
+ if [[ ! $got ]] && (( h ))
+ then got=HUNG
+ fi
+ if [[ ${TST[T].EXP} ]]
+ then exp=${TST[T].EXP}
+ else exp=$n
+ fi
+ if [[ $got != $exp ]]
+ then # on failure skip similar tests on larger files sizes #
+ SKIP[S][C][I][A][T]=1
+ siz=$(printf $'%#i' $exp)
+ cmd=${TST[T].CMD//\$cat/$cat}
+ cmd=${cmd//\$tmp\/buf/$siz.buf}
+ cmd=${cmd//\$tmp\/lin/$siz.lin}
+ err_exit "'x=${SUB[S].BEG}${INS[I]}${cmd}${APP[A]}${SUB[S].END} && print \${#x}' failed -- expected '$exp', got '$got'"
+ elif [[ ${TST[T].EXP} ]] || (( TST[T].LIM >= n ))
+ then SKIP[S][C][I][A][T]=1
+ fi
+ fi
+
+ #...indent#
+ done
+ done
+ done
+ done
+ done
+done
+
+# specifics -- there's more?
+
+{
+ cmd='{ exec 5>/dev/null; print "$(eval ls -d . 2>&1 1>&5)"; } >$tmp/out &'
+ eval $cmd
+ m=$!
+ { sleep 4; kill -9 $m; } &
+ k=$!
+ wait $m
+ h=$?
+ kill -9 $k
+ wait $k
+ got=$(<$tmp/out)
+} 2>/dev/null
+exp=''
+if [[ ! $got ]] && (( h ))
+then got=HUNG
+fi
+if [[ $got != $exp ]]
+then err_exit "eval '$cmd' failed -- expected '$exp', got '$got'"
+fi
+
+float t1=$SECONDS
+sleep=$(whence -p sleep)
+if [[ $sleep ]]
+then
+ $SHELL -c "( $sleep 5 </dev/null >/dev/null 2>&1 & );exit 0" | cat
+ (( (SECONDS-t1) > 4 )) && err_exit '/bin/sleep& in subshell hanging'
+ ((t1=SECONDS))
+fi
+$SHELL -c '( sleep 5 </dev/null >/dev/null 2>&1 & );exit 0' | cat
+(( (SECONDS-t1) > 4 )) && err_exit 'sleep& in subshell hanging'
+
exit $Errors
diff --git a/usr/src/lib/libshell/common/tests/substring.sh b/usr/src/lib/libshell/common/tests/substring.sh
index 8d283c6a29..0d7fc384a7 100644
--- a/usr/src/lib/libshell/common/tests/substring.sh
+++ b/usr/src/lib/libshell/common/tests/substring.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -192,7 +192,7 @@ fi
if [[ ${foo//\//_} != one_two_three ]]
then err_exit 'escaping / in replacements failed'
fi
-function myexport
+function myexport
{
nameref var=$1
if (( $# > 1 ))
@@ -205,7 +205,7 @@ function myexport
typeset val
val=$(export | grep "^$1=")
print ${val#"$1="}
-
+
}
export dgk=base
if [[ $(myexport dgk fun) != fun ]]
@@ -280,7 +280,7 @@ b='[abc 123 def]'
[[ ${b//$a/\1} == 123 ]] || err_exit "\${var/pattern} not working with \[ in pattern"
unset foo
foo='(win32.i386) '
-[[ ${foo/'('/'(x11-'} == '(x11-win32.i386) ' ]] || err_exit "\${var/pattern} not working with ' in pattern"
+[[ ${foo/'('/'(x11-'} == '(x11-win32.i386) ' ]] || err_exit "\${var/pattern} not working with ' in pattern"
$SHELL -c $'v=\'$(hello)\'; [[ ${v//\'$(\'/-I\'$(\'} == -I"$v" ]]' 2> /dev/null || err_exit "\${var/pattern} not working with \$( as pattern"
unset X
$SHELL -c '[[ ! ${X[@]:0:300} ]]' 2> /dev/null || err_exit '${X[@]:0:300} with X undefined fails'
@@ -303,7 +303,7 @@ 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'
+[[ ${.sh.match[@]:2:4} == 'B C D E' ]] || err_exit '${.sh.match[@]:2:4} incorrect'
D=$';' E=$'\\\\' Q=$'"' S=$'\'' M='nested pattern substitution failed'
@@ -501,7 +501,7 @@ 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 ]]
+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
@@ -509,10 +509,10 @@ 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'
+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'
+{ $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'
# subject mode pattern result #
set -- \
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_array_default_datatype.sh b/usr/src/lib/libshell/common/tests/sun_solaris_array_default_datatype.sh
new file mode 100644
index 0000000000..45b3851f19
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_array_default_datatype.sh
@@ -0,0 +1,303 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test module checks whether indexed+associative arrays
+# set the default datatype correctly if someone uses the "+="
+# operator to add a value to an array element which does not
+# exist yet.
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+# the test cannot use "nounset"
+Command=${0##*/}
+integer Errors=0
+
+compound bracketstat=(
+ integer bopen=0
+ integer bclose=0
+)
+
+function count_brackets
+{
+ typeset x="$1"
+ typeset c
+
+ integer i
+ (( bracketstat.bopen=0 , bracketstat.bclose=0 ))
+
+ for (( i=0 ; i < ${#x} ; i++ )) ; do
+ c="${x:i:1}"
+ [[ "$c" == "(" ]] && (( bracketstat.bopen++ ))
+ [[ "$c" == ")" ]] && (( bracketstat.bclose++ ))
+ done
+
+ (( bracketstat.bopen != bracketstat.bclose )) && return 1
+
+ return 0
+}
+
+# function to add the floating-point value 1.1 to array element "34"
+# floating-point datatypes should increment by 1.1, integers by 1
+function add_float
+{
+ nameref arr=$1
+
+ arr[34]+=1.1
+
+ return 0
+}
+
+# function to add a compound variable called "val" to array element arr[34]
+function add_compound
+{
+ nameref arr=$1
+
+ arr[34]+=( float val=1.1 )
+
+ return 0
+}
+
+# We run the tests in multiple cyles:
+# First cycle uses a normal compound variable as basis
+# Second cycle uses a nameref to a compound variable as basis
+# Third cycle uses a nameref to a nameref to a compound variable as basis
+for cycle in \
+ c1 c2 c3 c4 \
+ c2_sub c3_sub c4_sub \
+ c2_indexed_array c3_indexed_array c4_indexed_array \
+ c2_associative_array c3_associative_array c4_associative_array; do
+ case ${cycle} in
+ c1)
+ compound mycpv
+ ;;
+ c2)
+ compound rootcpv
+ nameref mycpv=rootcpv
+ ;;
+ c3)
+ compound rootcpv
+ nameref namereftoroot=rootcpv
+ nameref mycpv=namereftoroot
+ ;;
+ c4)
+ compound rootcpv
+ nameref namereftoroot0=rootcpv
+ nameref namereftoroot1=namereftoroot0
+ nameref mycpv=namereftoroot1
+ ;;
+ # same as cX but uses a subvariable of rootcpv
+ c2_sub)
+ compound rootcpv
+ compound rootcpv.sub
+ nameref mycpv=rootcpv.sub
+ ;;
+ c3_sub)
+ compound rootcpv
+ compound rootcpv.sub
+ nameref namereftoroot=rootcpv.sub
+ nameref mycpv=namereftoroot
+ ;;
+ c4_sub)
+ compound rootcpv
+ compound rootcpv.sub
+ nameref namereftoroot0=rootcpv.sub
+ nameref namereftoroot1=namereftoroot0
+ nameref mycpv=namereftoroot1
+ ;;
+ # same as cX but uses a subvariable of an indexed array
+ c2_indexed_array)
+ compound -a rootcpv
+ nameref mycpv=rootcpv[4]
+ ;;
+ c3_indexed_array)
+ compound -a rootcpv
+ nameref namereftoroot=rootcpv[4]
+ nameref mycpv=namereftoroot
+ ;;
+ c4_indexed_array)
+ compound -a rootcpv
+ nameref namereftoroot0=rootcpv[4]
+ nameref namereftoroot1=namereftoroot0
+ nameref mycpv=namereftoroot1
+ ;;
+ # same as cX but uses a subvariable of an indexed array
+ c2_associative_array)
+ compound -A rootcpv
+ nameref mycpv=rootcpv["hello world"]
+ ;;
+ c3_associative_array)
+ compound -A rootcpv
+ nameref namereftoroot=rootcpv["hello world"]
+ nameref mycpv=namereftoroot
+ ;;
+ c4_associative_array)
+ compound -A rootcpv
+ nameref namereftoroot0=rootcpv["hello world"]
+ nameref namereftoroot1=namereftoroot0
+ nameref mycpv=namereftoroot1
+ ;;
+ *)
+ err_exit "${cycle}: Should not happen."
+ ;;
+ esac
+
+
+ # Test 001: Test indexed floating-point array
+ float -a mycpv.myindexedfloatarray
+
+ add_float mycpv.myindexedfloatarray
+ (( mycpv.myindexedfloatarray[34] == 1.1 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 1.1"
+ add_float mycpv.myindexedfloatarray
+ (( mycpv.myindexedfloatarray[34] == 2.2 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 2.2"
+ unset mycpv.myindexedfloatarray[34]
+ (( mycpv.myindexedfloatarray[34] == 0.0 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 0.0"
+
+ # 2nd try (we do this to check whether "unset" works properly)
+ add_float mycpv.myindexedfloatarray
+ (( mycpv.myindexedfloatarray[34] == 1.1 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 1.1"
+ add_float mycpv.myindexedfloatarray
+ (( mycpv.myindexedfloatarray[34] == 2.2 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 2.2"
+ unset mycpv.myindexedfloatarray[34]
+ (( mycpv.myindexedfloatarray[34] == 0.0 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 0.0"
+
+
+
+ # Test 002: Test associative floating-point array
+ float -A mycpv.myassociativefloatarray
+ add_float mycpv.myassociativefloatarray
+ (( mycpv.myassociativefloatarray[34] == 1.1 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 1.1"
+ add_float mycpv.myassociativefloatarray
+ (( mycpv.myassociativefloatarray[34] == 2.2 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 2.2"
+ unset mycpv.myassociativefloatarray[34]
+ (( mycpv.myassociativefloatarray[34] == 0.0 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 0.0"
+
+ # 2nd try (we do this to check whether "unset" works properly)
+ add_float mycpv.myassociativefloatarray
+ (( mycpv.myassociativefloatarray[34] == 1.1 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 1.1"
+ add_float mycpv.myassociativefloatarray
+ (( mycpv.myassociativefloatarray[34] == 2.2 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 2.2"
+ unset mycpv.myassociativefloatarray[34]
+ (( mycpv.myassociativefloatarray[34] == 0.0 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 0.0"
+
+
+
+ # Test 003: Test indexed integer array
+ integer -a mycpv.myindexedintegerarray
+
+ add_float mycpv.myindexedintegerarray
+ (( mycpv.myindexedintegerarray[34] == 1 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 1"
+ add_float mycpv.myindexedintegerarray
+ (( mycpv.myindexedintegerarray[34] == 2 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 2"
+ unset mycpv.myindexedintegerarray[34]
+ (( mycpv.myindexedintegerarray[34] == 0 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 0"
+
+ # 2nd try (we do this to check whether "unset" works properly)
+ add_float mycpv.myindexedintegerarray
+ (( mycpv.myindexedintegerarray[34] == 1 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 1"
+ add_float mycpv.myindexedintegerarray
+ (( mycpv.myindexedintegerarray[34] == 2 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 2"
+ unset mycpv.myindexedintegerarray[34]
+ (( mycpv.myindexedintegerarray[34] == 0 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 0"
+
+
+
+ # Test 004: Test associative integer array
+ integer -A mycpv.myassociativeintegerarray
+
+ add_float mycpv.myassociativeintegerarray
+ (( mycpv.myassociativeintegerarray[34] == 1 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 1"
+ add_float mycpv.myassociativeintegerarray
+ (( mycpv.myassociativeintegerarray[34] == 2 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 2"
+ unset mycpv.myassociativeintegerarray[34]
+ (( mycpv.myassociativeintegerarray[34] == 0 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 0"
+
+ # 2nd try (we do this to check whether "unset" works properly)
+ add_float mycpv.myassociativeintegerarray
+ (( mycpv.myassociativeintegerarray[34] == 1 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 1"
+ add_float mycpv.myassociativeintegerarray
+ (( mycpv.myassociativeintegerarray[34] == 2 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 2"
+ unset mycpv.myassociativeintegerarray[34]
+ (( mycpv.myassociativeintegerarray[34] == 0 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 0"
+
+
+
+ # Test 005: Tested indexed compound variable array
+ compound -a mycpv.myindexedcompoundarray
+ add_compound mycpv.myindexedcompoundarray
+ (( mycpv.myindexedcompoundarray[34].val == 1.1 )) || err_exit "${cycle}: mycpv.myindexedcompoundarray[34].val == ${mycpv.myindexedcompoundarray[34].val}, expected 1.1"
+ # try to add it a 2nd time - since the new element will replace the old
+ # one the value will _not_ be incremented (or better: The compound
+ # variable value "val" will be added, not the value of the "val"
+ # variable)
+ add_compound mycpv.myindexedcompoundarray
+ (( mycpv.myindexedcompoundarray[34].val == 1.1 )) || err_exit "${cycle}: mycpv.myindexedcompoundarray[34].val == ${mycpv.myindexedcompoundarray[34].val}, expected 1.1"
+ unset mycpv.myindexedcompoundarray[34]
+ [[ ! -v mycpv.myindexedcompoundarray[34].val ]] || err_exit "${cycle}: [[ ! -v mycpv.myindexedcompoundarray[34].val ]] should return failure, got $?"
+ (( mycpv.myindexedcompoundarray[34].val == 0.0 )) || err_exit "${cycle}: mycpv.myindexedcompoundarray[34].val == ${mycpv.myindexedcompoundarray[34].val}, expected 0.0"
+ [[ "${mycpv.myindexedcompoundarray[34]}" == "" ]] || err_exit "${cycle}: mycpv.myindexedcompoundarray[34] expected to be equal to an empty string but contains |${mycpv.myindexedcompoundarray[34]}|"
+
+
+
+ # Test 006: Tested associative compound variable array
+ compound -A mycpv.myassociativecompoundarray
+ add_compound mycpv.myassociativecompoundarray
+ (( mycpv.myassociativecompoundarray[34].val == 1.1 )) || err_exit "${cycle}: mycpv.myassociativecompoundarray[34].val == ${mycpv.myassociativecompoundarray[34].val}, expected 1.1"
+ # try to add it a 2nd time - since the new element will replace the old
+ # one the value will _not_ be incremented (or better: The compound
+ # variable value "val" will be added, not the value of the "val"
+ # variable)
+ add_compound mycpv.myassociativecompoundarray
+ (( mycpv.myassociativecompoundarray[34].val == 1.1 )) || err_exit "${cycle}: mycpv.myassociativecompoundarray[34].val == ${mycpv.myassociativecompoundarray[34].val}, expected 1.1"
+ unset mycpv.myassociativecompoundarray[34]
+ [[ ! -v mycpv.myassociativecompoundarray[34].val ]] || err_exit "${cycle}: [[ ! -v mycpv.myassociativecompoundarray[34].val ]] should return failure, got $?"
+ (( mycpv.myassociativecompoundarray[34].val == 0.0 )) || err_exit "${cycle}: mycpv.myassociativecompoundarray[34].val == ${mycpv.myassociativecompoundarray[34].val}, expected 0.0"
+ [[ "${mycpv.myassociativecompoundarray[34]}" == "" ]] || err_exit "${cycle}: mycpv.myassociativecompoundarray[34] expected to be equal to an empty string but contains |${mycpv.myassociativecompoundarray[34]}|"
+
+
+ # check whether the compound variable output is still Ok
+ count_brackets "${mycpv}" || err_exit "${cycle}: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+ count_brackets "$(print -v mycpv)" || err_exit "${cycle}: print -v mycpy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+ count_brackets "$(print -C mycpv)" || err_exit "${cycle}: print -C mycpy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+
+
+ # reset
+ unset mycpv
+ [[ ! -v mycpv ]] || err_exit "${cycle}: mycpy should not exist"
+ [[ "${mycpv}" == "" ]] || err_exit "${cycle}: mycpv expected to be empty"
+done
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_builtin_poll.sh b/usr/src/lib/libshell/common/tests/sun_solaris_builtin_poll.sh
new file mode 100644
index 0000000000..5dc5f5cce1
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_builtin_poll.sh
@@ -0,0 +1,72 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Test whether the ksh93/poll builtin works as expected
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+
+builtin -f libshell.so.1 poll || err_exit "poll builtin not found."
+
+compound d1=(
+ compound -A u=(
+ [y]=( fd=5 events="POLLIN" revents="" )
+ [x]=( fd=5 events="POLLIN" revents="" )
+ )
+)
+
+# test 1:
+cat /dev/zero | { redirect 5<&0 ; poll -e d1.res -t 5. d1.u ; } || err_exit "poll returned non-zero exit code $?"
+[[ "${d1.u[x].revents}" == "POLLIN" ]] || err_exit "d1.u[x].revents contains '${d1.u[x].revents}', not POLLIN"
+[[ "${d1.u[y].revents}" == "POLLIN" ]] || err_exit "d1.u[y].revents contains '${d1.u[y].revents}', not POLLIN"
+[[ "${d1.res[*]}" == "x y" ]] || err_exit "d1.res contains '${d1.res[*]}', not 'x y'"
+
+# test 2:
+unset d1.res
+
+d1.u[z]=( fd=5 events="POLLOUT" revents="" )
+{ poll -e d1.res -t 5. d1.u ; } 5</dev/null 5>/dev/null || err_exit "poll returned non-zero exit code $?"
+[[ "${d1.u[x].revents}" == "POLLIN" ]] || err_exit "d1.u[x].revents contains '${d1.u[x].revents}', not 'POLLIN'"
+[[ "${d1.u[y].revents}" == "POLLIN" ]] || err_exit "d1.u[y].revents contains '${d1.u[y].revents}', not 'POLLIN'"
+[[ "${d1.u[z].revents}" == "POLLOUT|POLLWRNORM" ]] || err_exit "d1.u[z].revents contains '${d1.u[z].revents}', not 'POLLOUT|POLLWRNORM,'"
+[[ "${d1.res[*]}" == "x y z" ]] || err_exit "d1.res contains '${d1.res[*]}', not 'x y z'"
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_builtin_sum.sh b/usr/src/lib/libshell/common/tests/sun_solaris_builtin_sum.sh
index d2dc6db883..e80111a538 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_builtin_sum.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_builtin_sum.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -29,6 +29,7 @@
# Solaris/SystemV /usr/bin/sum
#
+# test setup
function err_exit
{
print -u2 -n "\t"
@@ -37,9 +38,11 @@ function err_exit
}
alias err_exit='err_exit $LINENO'
+set -o nounset
Command=${0##*/}
integer Errors=0
+
typeset x
builtin sum || err_exit "sum builtin not found"
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_builtin_tail.sh b/usr/src/lib/libshell/common/tests/sun_solaris_builtin_tail.sh
new file mode 100644
index 0000000000..69a7f1a6b9
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_builtin_tail.sh
@@ -0,0 +1,446 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Test whether the ksh93/libcmd tail builtin is compatible to
+# Solaris/SystemV { /usr/bin/tail, /usr/xpg4/bin/tail } and
+# POSIX "tail"
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+# common functions
+function isvalidpid
+{
+ kill -0 ${1} 2>/dev/null && return 0
+ return 1
+}
+
+function waitpidtimeout
+{
+ integer pid=$1
+ float timeout=$2
+ float i
+ float -r STEP=0.5 # const
+
+ (( timeout=timeout/STEP ))
+
+ for (( i=0 ; i < timeout ; i+=STEP )) ; do
+ isvalidpid ${pid} || break
+ sleep ${STEP}
+ done
+
+ return 0
+}
+
+function myintseq
+{
+ integer i
+ float arg1=$1
+ float arg2=$2
+ float arg3=$3
+
+ case $# in
+ 1)
+ for (( i=1 ; i <= arg1 ; i++ )) ; do
+ printf "%d\n" i
+ done
+ ;;
+ 2)
+ for (( i=arg1 ; i <= arg2 ; i++ )) ; do
+ printf "%d\n" i
+ done
+ ;;
+ 3)
+ for (( i=arg1 ; i <= arg3 ; i+=arg2 )) ; do
+ printf "%d\n" i
+ done
+ ;;
+ *)
+ print -u2 -f "%s: Illegal number of arguments %d\n" "$0" $#
+ return 1
+ ;;
+ esac
+
+ return 0
+}
+
+# quote input string but use double-backslash that "err_exit" prints
+# the strings correctly
+function doublebackslashquote
+{
+ typeset s
+ s="$(printf "%q\n" "$1")"
+ s="${s//\\/\\\\}"
+ print -r "$s"
+ return 0
+}
+
+
+# main
+builtin mktemp || err_exit "mktemp builtin not found"
+builtin rm || err_exit "rm builtin not found"
+builtin tail || err_exit "tail builtin not found"
+
+typeset ocwd
+typeset tmpdir
+
+# create temporary test directory
+ocwd="$PWD"
+tmpdir="$(mktemp -d "test_sun_solaris_builtin_tail.XXXXXXXX")" || err_exit "Cannot create temporary directory"
+
+cd "${tmpdir}" || err_exit "cd ${tmpdir} failed."
+
+
+# run tests:
+
+# test1: basic tests
+compound -a testcases=(
+ (
+ name="reverse_n"
+ input=$'hello\nworld'
+ compound -A tail_args=(
+ [legacy]=( argv=( "-r" ) )
+ )
+ expected_output=$'world\nhello'
+ )
+ (
+ name="revlist0n"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "-0" ) )
+ [std_like]=( argv=( "-n" "0" ) )
+ )
+ expected_output=$''
+ )
+ (
+ name="revlist0nr"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "-0r" ) )
+ [std_like]=( argv=( "-n" "0" "-r" ) )
+ [long_options]=( argv=( "--lines" "0" "--reverse" ) )
+ )
+ expected_output=$'' )
+ (
+ name="revlist1n"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "-1" ) )
+ [std_like]=( argv=( "-n" "1" ) )
+ [long_options]=( argv=( "--lines" "1" ) )
+ )
+ expected_output=$'4' )
+ (
+ name="revlist1nr"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "-1r" ) )
+ [std_like]=( argv=( "-n" "1" "-r" ) )
+ [long_options]=( argv=( "--lines" "1" "--reverse" ) )
+ )
+ expected_output=$'4'
+ )
+ (
+ name="revlist2n"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "-2" ) )
+ [std_like]=( argv=( "-n" "2" ) )
+ )
+ expected_output=$'3\n4'
+ )
+ (
+ name="revlist2nr"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "-2r" ) )
+ [std_like]=( argv=( "-n" "2" "-r" ) )
+ )
+ expected_output=$'4\n3'
+ )
+ (
+ name="revlist3nr"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "-3r" ) )
+ [std_like]=( argv=( "-n" "3" "-r" ) )
+ )
+ expected_output=$'4\n3\n2'
+ )
+ (
+ name="revlist2p"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "+2" ) )
+ [std_like]=( argv=( "-n" "+2" ) )
+ )
+ expected_output=$'2\n3\n4'
+ )
+ (
+ name="revlist2pr"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "+2r" ) )
+ [std_like]=( argv=( "-n" "+2" "-r" ) )
+ )
+ expected_output=$'4\n3\n2'
+ )
+ (
+ name="revlist3p"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "+3" ) )
+ [std_like]=( argv=( "-n" "+3" ) )
+ )
+ expected_output=$'3\n4'
+ )
+ (
+ name="revlist3pr"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "+3r" ) )
+ [std_like]=( argv=( "-n" "+3" "-r" ) )
+ )
+ expected_output=$'4\n3'
+ )
+ (
+ name="revlist4p"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "+4" ) )
+ [std_like]=( argv=( "-n" "+4" ) )
+ )
+ expected_output=$'4'
+ )
+ (
+ name="revlist4pr"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "+4r" ) )
+ [std_like]=( argv=( "-n" "+4" "-r" ) )
+ )
+ expected_output=$'4'
+ )
+ (
+ name="revlist5p"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "+5" ) )
+ [std_like]=( argv=( "-n" "+5" ) )
+ )
+ expected_output=$''
+ )
+ (
+ name="revlist5pr"
+ input=$'1\n2\n3\n4'
+ compound -A tail_args=(
+ [legacy]=( argv=( "+5r" ) )
+ [std_like]=( argv=( "-n" "+5" "-r" ) )
+ )
+ expected_output=$''
+ )
+)
+
+for testid in "${!testcases[@]}" ; do
+ nameref tc=testcases[${testid}]
+
+ for argv_variants in "${!tc.tail_args[@]}" ; do
+ nameref argv=tc.tail_args[${argv_variants}].argv
+ output=$(
+ #set -o pipefail
+ print -r -- "${tc.input}" | tail "${argv[@]}"
+ ) || err_exit "test ${tc.name}/${argv_variants}: command failed with exit code $?"
+
+ [[ "${output}" == "${tc.expected_output}" ]] || err_exit "test ${tc.name}/${argv_variants}: Expected $(doublebackslashquote "${tc.expected_output}"), got $(doublebackslashquote "${output}")"
+ done
+done
+
+
+# test2: test "tail -r </etc/profile | rev -l" vs. "cat </etc/profile"
+[[ "$(tail -r </etc/profile | rev -l)" == "$( cat /etc/profile )" ]] || err_exit "'tail -r </etc/profile | rev -l' output does not match 'cat /etc/profile'"
+
+
+# test 3: ast-ksh.2009-05-05 "tail" builtin may crash if we pass unsupported long options
+$SHELL -o errexit -c 'builtin tail ; print "hello" | tail --attack_of_chicken_monsters' >/dev/null 2>&1
+(( $? == 2 )) || err_exit "expected exit code 2 for unsupported long option, got $?"
+
+
+# test 4: FIFO tests
+
+# FIFO test functions
+# (we use functions here to do propper garbage collection)
+function test_tail_fifo_1
+{
+ typeset tail_cmd="$1"
+ integer i
+ integer tail_pid=-1
+
+ # cleanup trap
+ trap "rm -f tailtestfifo tailout" EXIT
+
+ # create test FIFO
+ mkfifo tailtestfifo
+
+ ${tail_cmd} -f <tailtestfifo >tailout &
+ tail_pid=$!
+
+ myintseq 20 >tailtestfifo
+
+ waitpidtimeout ${tail_pid} 5
+
+ if isvalidpid ${tail_pid} ; then
+ err_exit "test_tail_fifo_1: # tail hung (not expected)"
+ kill -KILL ${tail_pid}
+ fi
+
+ wait || err_exit "tail child returned non-zero exit code=$?"
+
+ [[ "$(cat tailout)" == $'11\n12\n13\n14\n15\n16\n17\n18\n19\n20' ]] || err_exit "test_tail_fifo_1: Expected $(doublebackslashquote '11\n12\n13\n14\n15\n16\n17\n18\n19\n20'), got $(doublebackslashquote "$(cat tailout)")"
+
+ return 0
+}
+
+function test_tail_fifo_2
+{
+ typeset tail_cmd="$1"
+ integer i
+ integer tail_pid=-1
+
+ # cleanup trap
+ trap "rm -f tailtestfifo tailout" EXIT
+
+ # create test FIFO
+ mkfifo tailtestfifo
+
+ ${tail_cmd} -f tailtestfifo >tailout &
+ tail_pid=$!
+
+ myintseq 14 >tailtestfifo
+
+ waitpidtimeout ${tail_pid} 5
+
+ if isvalidpid ${tail_pid} ; then
+ [[ "$(cat tailout)" == $'5\n6\n7\n8\n9\n10\n11\n12\n13\n14' ]] || err_exit "test_tail_fifo_2: Expected $(doublebackslashquote $'5\n6\n7\n8\n9\n10\n11\n12\n13\n14'), got $(doublebackslashquote "$(cat tailout)")"
+
+ myintseq 15 >>tailtestfifo
+
+ waitpidtimeout ${tail_pid} 5
+
+ if isvalidpid ${tail_pid} ; then
+ kill -KILL ${tail_pid}
+ else
+ err_exit "test_tail_fifo_2: # tail exit with return code $? (not expected)"
+ fi
+ fi
+
+ wait || err_exit "tail child returned non-zero exit code=$?"
+
+ [[ "$(cat tailout)" == $'5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15' ]] || err_exit "test_tail_fifo_2: Expected $(doublebackslashquote $'5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15'), got $(doublebackslashquote "$(cat tailout)")"
+
+ return 0
+}
+
+# fixme: This should test /usr/bin/tail and /usr/xpg4/bin/tail in Solaris
+test_tail_fifo_1 "tail"
+test_tail_fifo_2 "tail"
+
+
+# test 5: "tail -f" tests
+function followtest1
+{
+ typeset -r FOLLOWFILE="followfile.txt"
+ typeset -r OUTFILE="outfile.txt"
+
+ typeset title="$1"
+ typeset testcmd="$2"
+ typeset usenewline=$3
+ typeset followstr=""
+ typeset newline=""
+ integer i
+ integer tailchild=-1
+
+ if ${usenewline} ; then
+ newline=$'\n'
+ fi
+
+ rm -f "${FOLLOWFILE}" "${OUTFILE}"
+ print -n "${newline}" > "${FOLLOWFILE}"
+
+ ${testcmd} -f "${FOLLOWFILE}" >"${OUTFILE}" &
+ (( tailchild=$! ))
+
+ for (( i=0 ; i < 10 ; i++)) ; do
+ followstr+="${newline}${i}"
+ print -n "${i}${newline}" >>"${FOLLOWFILE}"
+ sleep 2
+
+ [[ "$( < "${OUTFILE}")" == "${followstr}" ]] || err_exit "${title}: Expected $(doublebackslashquote "${followstr}"), got "$(doublebackslashquote "$( < "${OUTFILE}")")""
+ done
+
+ #kill -TERM ${tailchild} 2>/dev/null
+ kill -KILL ${tailchild} 2>/dev/null
+ waitpidtimeout ${tailchild} 5
+
+ if isvalidpid ${tailchild} ; then
+ err_exit "${title}: tail pid=${tailchild} hung."
+ kill -KILL ${tailchild} 2>/dev/null
+ fi
+
+ wait ${tailchild} 2>/dev/null
+
+ rm -f "${FOLLOWFILE}" "${OUTFILE}"
+
+ return 0
+}
+
+followtest1 "test5a" "tail" true
+# fixme: later we should test this, too:
+#followtest1 "test5b" "tail" false
+#followtest1 "test5c" "/usr/xpg4/bin/tail" true
+#followtest1 "test5d" "/usr/xpg4/bin/tail" false
+#followtest1 "test5e" "/usr/bin/tail" true
+#followtest1 "test5f" "/usr/bin/tail" false
+
+
+# cleanup
+cd "${ocwd}"
+rmdir "${tmpdir}" || err_exit "Cannot remove temporary directory ${tmpdir}".
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_command_substitution.sh b/usr/src/lib/libshell/common/tests/sun_solaris_command_substitution.sh
new file mode 100644
index 0000000000..77ab14714e
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_command_substitution.sh
@@ -0,0 +1,291 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Written by Roland Mainz <roland.mainz@nrubsig.org>
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+
+function isvalidpid
+{
+ kill -0 ${1} 2>/dev/null && return 0
+ return 1
+}
+integer testfilesize i maxwait
+typeset tmpfile
+integer testid
+
+
+########################################################################
+#### test set 001:
+# run loop and check various temp filesizes
+# (Please keep this test syncted with sun_solaris_cr_6800929_large_command_substitution_hang.sh)
+
+# test 1: run loop and check various temp filesizes
+tmpfile="$(mktemp "/tmp/ksh93_tests_command_substitution.${PPID}.$$.XXXXXX")" || err_exit "Cannot create temporary file."
+
+compound test1=(
+ compound -a testcases=(
+ # test 1a: Run test child for $(...)
+ # (note the pipe chain has to end in a builtin command, an external command may not trigger the bug)
+ ( name="test1a" cmd="builtin cat ; print -- \"\$(cat \"${tmpfile}\" | cat)\" ; true" )
+ # test 1b: Same as test1a but uses ${... ; } instead if $(...)
+ ( name="test1b" cmd="builtin cat ; print -- \"\${ cat \"${tmpfile}\" | cat ; }\" ; true" )
+ # test 1c: Same as test1a but does not use a pipe
+ ( name="test1c" cmd="builtin cat ; print -- \"\$(cat \"${tmpfile}\" ; true)\" ; true" )
+ # test 1d: Same as test1a but does not use a pipe
+ ( name="test1d" cmd="builtin cat ; print -- \"\${ cat \"${tmpfile}\" ; true ; }\" ; true" )
+
+ # test 1e: Same as test1a but uses an external "cat" command
+ ( name="test1e" cmd="builtin -d cat /bin/cat ; print -- \"\$(cat \"${tmpfile}\" | cat)\" ; true" )
+ # test 1f: Same as test1a but uses an external "cat" command
+ ( name="test1f" cmd="builtin -d cat /bin/cat ; print -- \"\${ cat \"${tmpfile}\" | cat ; }\" ; true" )
+ # test 1g: Same as test1a but uses an external "cat" command
+ ( name="test1g" cmd="builtin -d cat /bin/cat ; print -- \"\$(cat \"${tmpfile}\" ; true)\" ; true" )
+ # test 1h: Same as test1a but uses an external "cat" command
+ ( name="test1h" cmd="builtin -d cat /bin/cat ; print -- \"\${ cat \"${tmpfile}\" ; true ; }\" ; true" )
+ )
+)
+
+for (( testfilesize=1*1024 ; testfilesize <= 1024*1024 ; testfilesize*=2 )) ; do
+ # Create temp file
+ {
+ for (( i=0 ; i < testfilesize ; i+=64 )) ; do
+ print "0123456789abcdef01234567890ABCDEF0123456789abcdef01234567890ABCDE"
+ done
+ } >"${tmpfile}"
+
+ # wait up to log2(i) seconds for the child to terminate
+ # (this is 10 seconds for 1KB and 19 seconds for 512KB)
+ (( maxwait=log2(testfilesize) ))
+
+ for testid in "${!test1.testcases[@]}" ; do
+ nameref currtst=test1.testcases[testid]
+ ${SHELL} -o errexit -c "${currtst.cmd}" >"${tmpfile}.out" &
+ (( childpid=$! ))
+
+ for (( i=0 ; i < maxwait ; i++ )) ; do
+ isvalidpid ${childpid} || break
+ sleep 0.25
+ done
+
+ if isvalidpid ${childpid} ; then
+ err_exit "${currtst.name}: child (pid=${childpid}) still busy, filesize=${testfilesize}."
+ kill -KILL ${childpid} 2>/dev/null
+ fi
+ wait || err_exit "${currtst.name}: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime)
+
+ # compare input/output
+ cmp -s "${tmpfile}" "${tmpfile}.out" || err_exit "${currtst.name}: ${tmpfile} and ${tmpfile}.out differ, filesize=${testfilesize}."
+ rm "${tmpfile}.out"
+ done
+
+ # Cleanup
+ rm "${tmpfile}"
+done
+
+
+########################################################################
+#### test set 002:
+# If a command substitution calls a function and that function contains
+# a command substitution which contains a piped command, the original
+# command substitution calling the function will return 127 instead of 0.
+# This is causing problems in several VSC tests.
+# If we remove the piped command from the simple
+# case in the attached script, it returns 0.
+
+typeset str
+typeset testbody
+typeset testout
+
+testbody=$(
+# <CS> means command substitution start, <CE> means command substitution end
+cat <<EOF
+myfunc ()
+{
+ pipedcmd=<CS> printf "hi" | tr "h" "H" <CE>
+ echo \$pipedcmd
+
+ return 0
+}
+
+foo=<CS>myfunc<CE>
+retval=\$?
+
+if [ "\$foo"X != "HiX" ]; then
+ echo "myfunc returned '\${foo}'; expected 'Hi'"
+fi
+
+if [ \$retval -ne 0 ]; then
+ echo "command substitution calling myfunc returned \"\${retval}\"; expected 0"
+else
+ echo "command substitution calling myfunc successfully returned 0"
+fi
+EOF
+)
+
+
+# Test 002/a: Plain test
+testout=${ printf "%B\n" testbody | sed 's/<CS>/$(/g;s/<CE>/)/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" }
+[[ "${testout}" == "command substitution calling myfunc successfully returned 0" ]] || err_exit "Expected 'command substitution calling myfunc successfully returned 0', got ${testout}"
+
+# Test 002/b: Same as test002/a but replaces "$(" with "${"
+testout=${ printf "%B\n" testbody | sed 's/<CS>/${ /g;s/<CE>/ ; }/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" }
+[[ "${testout}" == "command substitution calling myfunc successfully returned 0" ]] || err_exit "Expected 'command substitution calling myfunc successfully returned 0', got ${testout}"
+
+# Test 002/c: Same as test002/a but forces |fork()| for a subshell via "ulimit -c 0"
+testout=${ printf "%B\n" testbody | sed 's/<CS>/$( ulimit -c 0 ; /g;s/<CE>/)/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" }
+[[ "${testout}" == "command substitution calling myfunc successfully returned 0" ]] || err_exit "Expected 'command substitution calling myfunc successfully returned 0', got ${testout}"
+
+# Test 002/d: Same as test002/a but uses extra subshell
+testout=${ printf "%B\n" testbody | sed 's/<CS>/$( ( /g;s/<CE>/) )/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" }
+[[ "${testout}" == "command substitution calling myfunc successfully returned 0" ]] || err_exit "Expected 'command substitution calling myfunc successfully returned 0', got ${testout}"
+
+# Test 002/e: Same as test002/b but uses extra subshell after "${ "
+testout=${ printf "%B\n" testbody | sed 's/<CS>/${ ( /g;s/<CE>/) ; }/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" }
+[[ "${testout}" == "command substitution calling myfunc successfully returned 0" ]] || err_exit "Expected 'command substitution calling myfunc successfully returned 0', got ${testout}"
+
+
+
+
+########################################################################
+#### test set 003:
+# An expression within backticks which should return false, instead
+# returns true (0).
+
+typeset str
+typeset testbody
+typeset testout
+
+testbody=$(
+# <CS> means command substitution start, <CE> means command substitution end
+cat <<EOF
+if <CS>expr "NOMATCH" : ".*Z" > /dev/null<CE> ; then
+ echo "xerror"
+else
+ echo "xok"
+fi
+EOF
+)
+
+
+# Test 003/a: Plain test
+testout=${ printf "%B\n" testbody | sed 's/<CS>/$(/g;s/<CE>/)/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" }
+[[ "${testout}" == "xok" ]] || err_exit "Expected 'xok', got ${testout}"
+
+# Test 003/b: Same as test003/a but replaces "$(" with "${"
+testout=${ printf "%B\n" testbody | sed 's/<CS>/${ /g;s/<CE>/ ; }/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" }
+[[ "${testout}" == "xok" ]] || err_exit "Expected 'xok', got ${testout}"
+
+# Test 003/c: Same as test003/a but forces |fork()| for a subshell via "ulimit -c 0"
+testout=${ printf "%B\n" testbody | sed 's/<CS>/$( ulimit -c 0 ; /g;s/<CE>/)/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" }
+[[ "${testout}" == "xok" ]] || err_exit "Expected 'xok', got ${testout}"
+
+# Test 003/d: Same as test003/a but uses extra subshell
+testout=${ printf "%B\n" testbody | sed 's/<CS>/$( ( /g;s/<CE>/) )/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" }
+[[ "${testout}" == "xok" ]] || err_exit "Expected 'xok', got ${testout}"
+
+# Test 003/e: Same as test003/b but uses extra subshell after "${ "
+testout=${ printf "%B\n" testbody | sed 's/<CS>/${ ( /g;s/<CE>/) ; }/g' | ${SHELL} 2>&1 || err_exit "command returned exit code $?" }
+[[ "${testout}" == "xok" ]] || err_exit "Expected 'xok', got ${testout}"
+
+
+########################################################################
+#### test set 004:
+# test pipe within ${... ; } command subtitution ending in a
+# non-builtin command (therefore we use "/bin/cat" instead of "cat" below
+# to force the use of the external "cat" command). ast-ksh.2009-01-20
+# had a bug which caused this test to fail.
+testout=$( ${SHELL} -c 'pipedcmd=${ printf "hi" | /bin/cat ; } ; print $pipedcmd' )
+[[ "${testout}" == "hi" ]] || err_exit "test004: Expected 'hi', got '${testout}'"
+
+
+########################################################################
+#### test set 005:
+# Test whether the shell may hang in a
+# 'exec 5>/dev/null; print $(eval ls -d . 2>&1 1>&5)'
+# Originally discovered with ast-ksh.2009-05-05 which hung in
+# the "configure" script of postgresql-8.3.7.tar.gz (e.g.
+# configure --enable-thread-safety --without-readline)
+compound test5=(
+ compound -a testcases=(
+ # gsf's reduced testcase
+ ( name="test5_a" cmd='exec 5>/dev/null; print $(eval ls -d . 2>&1 1>&5)done' )
+ # gisburn's reduced testcase
+ ( name="test5_b" cmd='exec 5>/dev/null; print $(eval "/bin/printf hello\n" 2>&1 1>&5)done' )
+
+ ## The following tests do not trigger the problem but are included here for completeness
+ ## and to make sure we don't get other incarnations of the same problem later...
+
+ # same as test5_a but uses ${ ... ; } instead of $(...)
+ ( name="test5_c" cmd='exec 5>/dev/null; print "${ eval ls -d . 2>&1 1>&5 ;}done"' )
+ # same as test5_b but uses ${ ... ; } instead of $(...)
+ ( name="test5_d" cmd='exec 5>/dev/null; print "${ eval "/bin/printf hello\n" 2>&1 1>&5 ;}done"' )
+ # same as test5_a but uses "ulimit -c 0" to force the shell to use a seperare process for $(...)
+ ( name="test5_e" cmd='exec 5>/dev/null; print $(ulimit -c 0 ; eval ls -d . 2>&1 1>&5)done' )
+ # same as test5_b but uses "ulimit -c 0" to force the shell to use a seperare process for $(...)
+ ( name="test5_f" cmd='exec 5>/dev/null; print $(ulimit -c 0 ; eval "/bin/printf hello\n" 2>&1 1>&5)done' )
+ )
+)
+
+maxwait=5
+for testid in "${!test5.testcases[@]}" ; do
+ nameref currtst=test5.testcases[testid]
+ ${SHELL} -o errexit -c "${currtst.cmd}" >"${tmpfile}.out" &
+ (( childpid=$! ))
+
+ for (( i=0 ; i < maxwait ; i++ )) ; do
+ isvalidpid ${childpid} || break
+ sleep 0.25
+ done
+
+ if isvalidpid ${childpid} ; then
+ err_exit "${currtst.name}: child (pid=${childpid}) still busy."
+ kill -KILL ${childpid} 2>/dev/null
+ fi
+ wait || err_exit "${currtst.name}: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime)
+
+ testout="$( < "${tmpfile}.out")"
+ rm "${tmpfile}.out" || err_exit "File '${tmpfile}.out' could not be removed."
+ [[ "${testout}" == "done" ]] || err_exit "test '${currtst.name}' failed, expected 'done', got '${testout}'"
+done
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_compound_nameref.sh b/usr/src/lib/libshell/common/tests/sun_solaris_compound_nameref.sh
new file mode 100644
index 0000000000..3714227449
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_compound_nameref.sh
@@ -0,0 +1,215 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+#
+# name reference test #001
+# Note we run this test in a seperate shell to make sure the memory
+# corruption originally reported can be reproduced (which precisely
+# depends on ordering in the testcase)
+(
+cat <<EOF
+ function err_exit
+ {
+ print -u2 -n "\t"
+ print -u2 -r \${Command}[\$1]: "\${@:2}"
+ (( Errors++ ))
+ }
+ alias err_exit='err_exit \$LINENO'
+
+ function function2
+ {
+ nameref v=\$1
+
+ v.x=19
+ v.y=20
+ }
+
+ function function1
+ {
+ typeset compound_var=()
+
+ function2 compound_var
+
+ printf "x=%d, y=%d\n" compound_var.x compound_var.y
+ }
+
+ x="\$(function1)"
+
+ [[ "\$x" == 'x=19, y=20' ]] || err_exit "expected 'x=19, y=20', got '\${x}'"
+
+EOF
+) | ${SHELL}
+(( Errors+=$? ))
+
+
+#
+# name reference test #002
+# Originally derived from the xmldocumenttree1.sh demo which failed
+# with ast-ksh.2009-04-15 since the nodepath+nodesnum nameref calls
+# were removing the compound variable members nodes+nodesnum (caused
+# by a scoping bug)
+#
+(
+cat <<EOF
+ compound xdoc
+ compound -A xdoc.nodes
+ integer xdoc.nodesnum=0
+
+ function test1
+ {
+ nameref doc=xdoc
+ nameref nodepath="doc.nodes"
+ nameref nodesnum="doc.nodesnum"
+ print -v doc
+ }
+
+ test1
+EOF
+) | out=$( ${SHELL} ) || err_exit "shell returned exit code $?"
+
+(( ${ wc -l <<<"${out}" ; } == 4 )) || err_exit "Expected four lines of output, got ${out}"
+(set -o errexit ; read -C tmp <<<"${out}" ; [[ "$(typeset +p tmp.nodes)" == *-A* ]]) || err_exit "missing variable tmp.nodes"
+(set -o errexit ; read -C tmp <<<"${out}" ; [[ -v tmp.nodesnum ]]) || err_exit "missing variable tmp.nodesnum"
+
+
+#
+# name reference test #003a
+# ast-ksh.2009-06-30 failed with the following compound variable/nameref test
+#
+(
+cat <<EOF
+ compound -A addrsp
+
+ nameref sp=addrsp
+
+ sp[14]=( size=1 )
+
+ if [[ -v sp[19] ]] ; then
+ print "should not happen"
+ else
+ print "Ok"
+ fi
+EOF
+) | out=$( ${SHELL} ) || err_exit "shell returned exit code $?"
+[[ "${out}" == "Ok" ]] || err_exit "Expected 'Ok', got ${out}"
+
+
+#
+# name reference test #003b
+# (same as test #003a but uses a function)
+# ast-ksh.2009-06-30 failed with the following compound variable/nameref test
+#
+(
+cat <<EOF
+ compound -A addrsp
+
+ function t1
+ {
+ nameref sp=\$1
+
+ sp[14]=( size=1 )
+
+ if [[ -v sp[19] ]] ; then
+ print "should not happen"
+ else
+ print "Ok"
+ fi
+ }
+
+ t1 addrsp
+EOF
+) | out=$( ${SHELL} ) || err_exit "shell returned exit code $?"
+[[ "${out}" == "Ok" ]] || err_exit "Expected 'Ok', got ${out}"
+
+
+#
+# name reference test #004a
+# (same as #003a but uses an indexed array instead of an associative one)
+# ast-ksh.2009-06-30 failed with the following compound variable/nameref test
+#
+(
+cat <<EOF
+ compound -a addrsp
+
+ nameref sp=addrsp
+
+ sp[14]=( size=1 )
+
+ if [[ -v sp[19] ]] ; then
+ print "should not happen"
+ else
+ print "Ok"
+ fi
+EOF
+) | out=$( ${SHELL} ) || err_exit "shell returned exit code $?"
+[[ "${out}" == "Ok" ]] || err_exit "Expected 'Ok', got ${out}"
+
+
+#
+# name reference test #004b
+# (same as test #004a but uses a function)
+# ast-ksh.2009-06-30 failed with the following compound variable/nameref test
+#
+(
+cat <<EOF
+ compound -a addrsp
+
+ function t1
+ {
+ nameref sp=\$1
+
+ sp[14]=( size=1 )
+
+ if [[ -v sp[19] ]] ; then
+ print "should not happen"
+ else
+ print "Ok"
+ fi
+ }
+
+ t1 addrsp
+EOF
+) | out=$( ${SHELL} ) || err_exit "shell returned exit code $?"
+[[ "${out}" == "Ok" ]] || err_exit "Expected 'Ok', got ${out}"
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_compoundvario.sh b/usr/src/lib/libshell/common/tests/sun_solaris_compoundvario.sh
index 18aed2aa7a..52bc5dca82 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_compoundvario.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_compoundvario.sh
@@ -20,20 +20,25 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
-typeset -C bracketstat=(
+# "nounset" disabled for now
+#set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+compound bracketstat=(
integer bopen=0
integer bclose=0
)
@@ -57,7 +62,45 @@ function count_brackets
return 0
}
-integer Errors=0
+# compound variable "cat" nr.1, using $ print "%B\n" ... #
+function cpvcat1
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do printf "%B\n" tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.2, using $ print "%#B\n" ... #
+function cpvcat2
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do printf "%#B\n" tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.3, using $ print -C ... #
+function cpvcat3
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do print -C tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.4, using $ print -v ... #
+function cpvcat4
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do print -v tmp ; done
+ return 0
+}
typeset s
@@ -71,7 +114,7 @@ typeset s
# -- snip --
# (additionally we test some extra stuff like bracket count)
s=${
- typeset -C x=(
+ compound x=(
a=1 b=2
typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
@@ -88,7 +131,7 @@ s=${
integer at=90
)
[e]=(
- typeset -C nested_cpv=(
+ compound nested_cpv=(
typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
typeset str=$'a \'string'
)
@@ -96,13 +139,19 @@ s=${
[f]=(
typeset g="f"
)
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
)
)
{
printf "%B\n" x
print "hello"
- } | {
+ } | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | {
read -C y
read s
}
@@ -111,6 +160,8 @@ s=${
[[ "${s}" == "xhellox" ]] || err_exit "Expected 'xhellox', got ${s}"
count_brackets "$y" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y)" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y)" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
# cleanup
unset x y || err_exit "unset failed"
@@ -128,11 +179,11 @@ unset x y || err_exit "unset failed"
# <compound var>
# -- snip --
s=${
- typeset -C x=(
+ compound x=(
a=1 b=2
typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
- typeset -A myarray3=(
+ compound -A myarray3=(
[a]=(
float m1=0.5
float m2=0.6
@@ -145,7 +196,7 @@ s=${
integer at=90
)
[e]=(
- typeset -C nested_cpv=(
+ compound nested_cpv=(
typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
typeset str=$'a \'string'
)
@@ -153,6 +204,12 @@ s=${
[f]=(
typeset g="f"
)
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
)
)
@@ -160,7 +217,7 @@ s=${
printf "%B\n" x
print "hello"
printf "%B\n" x
- } | {
+ } | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | {
read -C y1
read s
read -C y2
@@ -170,10 +227,22 @@ s=${
} || err_exit "test returned exit code $?"
[[ "${s}" == "xhellox" ]] || err_exit "Expected 'xhellox', got ${s}."
+[[ "${y1.myarray3[b].foo}" == "bar" ]] || err_exit "y1.myarray3[b].foo != bar"
+[[ "${y2.myarray3[b].foo}" == "bar" ]] || err_exit "y2.myarray3[b].foo != bar"
[[ "$y1" != "" ]] || err_exit "y1 is empty"
[[ "$y2" != "" ]] || err_exit "y2 is empty"
+(( ${#y1.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in y1.myarray3[e].nested_cpv, got ${#y1.myarray3[e].nested_cpv[@]}"
+(( ${#y2.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in y2.myarray3[e].nested_cpv, got ${#y2.myarray3[e].nested_cpv[@]}"
+(( isnan(y1.myarray3[a_nan].my_nan) )) || err_exit "y1.myarray3[a_nan].my_nan not a NaN"
+(( isnan(y2.myarray3[a_nan].my_nan) )) || err_exit "y2.myarray3[a_nan].my_nan not a NaN"
+(( signbit(y1.myarray3[a_nan].my_nan) )) || err_exit "y1.myarray3[a_nan].my_nan not negative"
+(( signbit(y2.myarray3[a_nan].my_nan) )) || err_exit "y2.myarray3[a_nan].my_nan not negative"
count_brackets "$y1" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y1)" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y1)" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
count_brackets "$y2" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y2)" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y2)" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
[[ "$y1" == "$y2" ]] || err_exit "Expected $(printf "%q\n" "${y1}") == $(printf "%q\n" "${y2}")."
[[ "$x" == "$y1" ]] || err_exit "Expected $(printf "%q\n" "${x}") == $(printf "%q\n" "${y}")."
@@ -185,11 +254,11 @@ unset x y1 y2 || err_exit "unset failed"
# Test 3: Test compound variable copy operator vs. "read -C"
-typeset -C x=(
+compound x=(
a=1 b=2
typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
- typeset -A myarray3=(
+ compound -A myarray3=(
[a]=(
float m1=0.5
float m2=0.6
@@ -202,7 +271,7 @@ typeset -C x=(
integer at=90
)
[e]=(
- typeset -C nested_cpv=(
+ compound nested_cpv=(
typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
typeset str=$'a \'string'
)
@@ -210,27 +279,41 @@ typeset -C x=(
[f]=(
typeset g="f"
)
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
)
)
-typeset -C x_copy=x || err_exit "x_copy copy failed"
+compound x_copy=x || err_exit "x_copy copy failed"
[[ "${x_copy}" != "" ]] || err_exit "x_copy should not be empty"
count_brackets "${x_copy}" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v x_copy)" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C x_copy)" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
-typeset -C nested_cpv_copy
+compound nested_cpv_copy
nested_cpv_copy=x.myarray3[e].nested_cpv || err_exit "x.myarray3[e].nested_cpv copy failed"
+(( ${#nested_cpv_copy.myarray[@]} == 10 )) || err_exit "Expected 10 elements in nested_cpv_copy.myarray, got ${#nested_cpv_copy.myarray[@]}"
# unset branch "x.myarray3[e].nested_cpv" of the variable tree "x" ...
unset x.myarray3[e].nested_cpv || err_exit "unset x.myarray3[e].nested_cpv failed"
[[ "${x.myarray3[e].nested_cpv}" == "" ]] || err_exit "x.myarray3[e].nested_cpv still has a value"
# ... and restore it from the saved copy
-printf "%B\n" nested_cpv_copy | read -C x.myarray3[e].nested_cpv || err_exit "read failed"
+printf "%B\n" nested_cpv_copy | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | read -C x.myarray3[e].nested_cpv || err_exit "read failed"
# compare copy of the original tree and the modified one
[[ "${x}" == "${x_copy}" ]] || err_exit "x != x_copy"
count_brackets "${x}" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v x)" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C x)" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+(( ${#x.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in x.myarray3[e].nested_cpv, got ${#x.myarray3[e].nested_cpv[@]}"
+(( isnan(x.myarray3[a_nan].my_nan) )) || err_exit "x.myarray3[a_nan].my_nan not a NaN"
+(( signbit(x.myarray3[a_nan].my_nan) )) || err_exit "x.myarray3[a_nan].my_nan not negative"
# cleanup
unset x x_copy nested_cpv_copy || err_exit "unset failed"
@@ -238,14 +321,15 @@ unset x x_copy nested_cpv_copy || err_exit "unset failed"
# Test 4: Test "read -C" failure for missing bracket at the end
typeset s
-s=$($SHELL -c 'typeset -C myvar ; print "( unfinished=1" | read -C myvar 2>/dev/null || print "error $?"') || err_exit "shell failed"
+s=$($SHELL -c 'compound myvar ; print "( unfinished=1" | read -C myvar 2>/dev/null || print "error $?"') || err_exit "shell failed"
[[ "$s" == "error 3" ]] || err_exit "compound_read: expected error 3, got ${s}"
# Test 5: Test "read -C" failure for missing bracket at the beginning
typeset s
-s=$($SHELL -c 'typeset -C myvar ; print " unfinished=1 )" | read -C myvar 2>/dev/null || print "error $?"') || err_exit "shell failed"
+s=$($SHELL -c 'compound myvar ; print " unfinished=1 )" | read -C myvar 2>/dev/null || print "error $?"') || err_exit "shell failed"
[[ "$s" == "error 3" ]] || err_exit "compound_read: expected error 3, got ${s}"
+
# tests done
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6687139_command_substitution_exec_redirection_allocation_loop.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6687139_command_substitution_exec_redirection_allocation_loop.sh
index 335470aa79..27cac4aa88 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6687139_command_substitution_exec_redirection_allocation_loop.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6687139_command_substitution_exec_redirection_allocation_loop.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -46,6 +46,7 @@
# -- snip --
#
+# test setup
function err_exit
{
print -u2 -n "\t"
@@ -54,15 +55,16 @@ function err_exit
}
alias err_exit='err_exit $LINENO'
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
function isvalidpid
{
kill -0 ${1} 2>/dev/null && return 0
return 1
}
-Command=${0##*/}
-integer Errors=0
-
integer childpid
typeset testdir
integer childretval
@@ -208,5 +210,6 @@ childretval=$?
cd /tmp
rmdir "${testdir}" || err_exit "Could not remove temporary test directory ${testdir}"
+
# tests done
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6713682_compound_var_bleeds_through_subshell.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6713682_compound_var_bleeds_through_subshell.sh
index 4f03984951..28a84caff1 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6713682_compound_var_bleeds_through_subshell.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6713682_compound_var_bleeds_through_subshell.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -51,17 +51,20 @@
# ... provides the correct output.
#
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
+set -o nounset
+Command=${0##*/}
integer Errors=0
+
typeset var1 var2
# use unset, l=() compound syntax and print
@@ -75,13 +78,13 @@ var2="$(${SHELL} -c '( ulimit -c 0 ; l=( a=1 b="BE" ) ; print "$l" ) ; print $l'
[[ "${var1}" == "${var2}" ]] || err_exit "Non-fork()'ed subshell output differes from fork()'ed subshell output (without unset)."
# use unset, typeset -C compound syntax and print
-var1="$(${SHELL} -c 'unset l ; ( typeset -C l ; l.a=1 ; l.b="BE" ; print "$l" ) ; print $l')" || err_exit "Non-zero exit code."
-var2="$(${SHELL} -c 'unset l ; ( ulimit -c 0 ; typeset -C l ; l.a=1 ; l.b="BE" ; print "$l" ) ; print $l')" || err_exit "Non-zero exit code."
+var1="$(${SHELL} -c 'unset l ; ( compound l ; l.a=1 ; l.b="BE" ; print "$l" ) ; print $l')" || err_exit "Non-zero exit code."
+var2="$(${SHELL} -c 'unset l ; ( ulimit -c 0 ; compound l ; l.a=1 ; l.b="BE" ; print "$l" ) ; print $l')" || err_exit "Non-zero exit code."
[[ "${var1}" == "${var2}" ]] || err_exit "Non-fork()'ed subshell output differes from fork()'ed subshell output (with unset)."
# do not use unset, typeset -C compound syntax and print
-var1="$(${SHELL} -c '( typeset -C l ; l.a=1 ; l.b="BE" ; print "$l" ) ; print $l')" || err_exit "Non-zero exit code."
-var2="$(${SHELL} -c '( ulimit -c 0 ; typeset -C l ; l.a=1 ; l.b="BE" ; print "$l" ) ; print $l')" || err_exit "Non-zero exit code."
+var1="$(${SHELL} -c '( compound l ; l.a=1 ; l.b="BE" ; print "$l" ) ; print $l')" || err_exit "Non-zero exit code."
+var2="$(${SHELL} -c '( ulimit -c 0 ; compound l ; l.a=1 ; l.b="BE" ; print "$l" ) ; print $l')" || err_exit "Non-zero exit code."
[[ "${var1}" == "${var2}" ]] || err_exit "Non-fork()'ed subshell output differes from fork()'ed subshell output (with unset)."
# use unset, l=() compound syntax and printf "%B\n"
@@ -95,14 +98,15 @@ var2="$(${SHELL} -c '( ulimit -c 0 ; l=( a=1 b="BE" ) ; printf "%B\n" l) ; print
[[ "${var1}" == "${var2}" ]] || err_exit "Non-fork()'ed subshell output differes from fork()'ed subshell output (without unset)."
# use unset, typeset -C compound syntax and printf "%B\n"
-var1="$(${SHELL} -c 'unset l ; ( typeset -C l ; l.a=1 ; l.b="BE" ; printf "%B\n" l) ; printf "%B\n" l')" || err_exit "Non-zero exit code."
-var2="$(${SHELL} -c 'unset l ; ( ulimit -c 0 ; typeset -C l ; l.a=1 ; l.b="BE" ; printf "%B\n" l) ; printf "%B\n" l')" || err_exit "Non-zero exit code."
+var1="$(${SHELL} -c 'unset l ; ( compound l ; l.a=1 ; l.b="BE" ; printf "%B\n" l) ; printf "%B\n" l')" || err_exit "Non-zero exit code."
+var2="$(${SHELL} -c 'unset l ; ( ulimit -c 0 ; compound l ; l.a=1 ; l.b="BE" ; printf "%B\n" l) ; printf "%B\n" l')" || err_exit "Non-zero exit code."
[[ "${var1}" == "${var2}" ]] || err_exit "Non-fork()'ed subshell output differes from fork()'ed subshell output (with unset)."
# do not use unset, typeset -C compound syntax and printf "%B\n"
-var1="$(${SHELL} -c '( typeset -C l ; l.a=1 ; l.b="BE" ; printf "%B\n" l) ; printf "%B\n" l')" || err_exit "Non-zero exit code."
-var2="$(${SHELL} -c '( ulimit -c 0 ; typeset -C l ; l.a=1 ; l.b="BE" ; printf "%B\n" l) ; printf "%B\n" l')" || err_exit "Non-zero exit code."
+var1="$(${SHELL} -c '( compound l ; l.a=1 ; l.b="BE" ; printf "%B\n" l) ; printf "%B\n" l')" || err_exit "Non-zero exit code."
+var2="$(${SHELL} -c '( ulimit -c 0 ; compound l ; l.a=1 ; l.b="BE" ; printf "%B\n" l) ; printf "%B\n" l')" || err_exit "Non-zero exit code."
[[ "${var1}" == "${var2}" ]] || err_exit "Non-fork()'ed subshell output differes from fork()'ed subshell output (with unset)."
+
# tests done
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6722134_background_CHLD_trap.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6722134_background_CHLD_trap.sh
index 333f5cc1a0..793d53d20d 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6722134_background_CHLD_trap.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6722134_background_CHLD_trap.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -40,17 +40,20 @@
# -- snip --
#
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
+set -o nounset
+Command=${0##*/}
integer Errors=0
+
##
## test one:
##
@@ -115,5 +118,6 @@ print "done"
(( count=$(fgrep "got_child" <<< "$s" | wc -l) )) || err_exit "counting failed."
(( count == 3 )) || err_exit "Expected count==3, got count==${count}."
+
# tests done
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6753538_subshell_leaks_umask.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6753538_subshell_leaks_umask.sh
index c755f86c87..fa016f4c67 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6753538_subshell_leaks_umask.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6753538_subshell_leaks_umask.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -40,17 +40,20 @@
# -- snip --
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
+set -o nounset
+Command=${0##*/}
integer Errors=0
+
#
# test set 1: Simple umask in subshell
#
@@ -93,5 +96,6 @@ x=$(${SHELL} -c 'umask 0; ( umask 20); umask') || err_exit "shell
y=$(${SHELL} -c 'umask 0; (ulimit -c 0 ; umask 20); umask') || err_exit "shell failed."
[[ "$x" == "$y" ]] || err_exit "$x != $y"
+
# tests done
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6754020_weird_square_bracket_expansion.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6754020_weird_square_bracket_expansion.sh
index d4bd345833..6b0092d5ba 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6754020_weird_square_bracket_expansion.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6754020_weird_square_bracket_expansion.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -45,17 +45,20 @@
# ---- snip ----
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
+set -o nounset
+Command=${0##*/}
integer Errors=0
+
typeset s
# test using "echo"
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6763594_command_failure_execs_twice.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6763594_command_failure_execs_twice.sh
index f3ffae5e84..bc3426f063 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6763594_command_failure_execs_twice.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6763594_command_failure_execs_twice.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -63,17 +63,20 @@
# ---- snip ----
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
+set -o nounset
+Command=${0##*/}
integer Errors=0
+
typeset testtmpdir=/tmp/ksh93_test_cr_6763594_${PPID}_$$
mkdir "${testtmpdir}" || { err_exit "Could not create temporary directory ${testtmpdir}." ; exit ${Errors} ; }
@@ -90,6 +93,7 @@ s=$( < out_stderr ) ; [[ "$s" == ~(Elr)(.*:\ \./myfoo:\ \./myfoo:\ .*\[.*\]) ]]
rm "myfoo" "out_stdout" "out_stderr" || err_exit "rm failed."
cd ..
rmdir "${testtmpdir}" || err_exit "Failed to remove temporary directory ${testtmpdir}."
-
+
+
# tests done
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6766246_pattern_matching_bug.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6766246_pattern_matching_bug.sh
index fc83db0e8a..7463baea5a 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6766246_pattern_matching_bug.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6766246_pattern_matching_bug.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -70,15 +70,17 @@
# ---- snip ----
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
+set -o nounset
+Command=${0##*/}
integer Errors=0
@@ -168,5 +170,6 @@ while (( $# >= 13 )) ; do
done
done
+
# tests done
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6769332_substitutions_terminate_shell_after_257_iterations.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6769332_substitutions_terminate_shell_after_257_iterations.sh
new file mode 100644
index 0000000000..7f76862bdd
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6769332_substitutions_terminate_shell_after_257_iterations.sh
@@ -0,0 +1,124 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether ksh93 supports more than 256 recursive
+# function+command substitution calls.
+#
+# This was reported as CR #6769332 ('Recursive function+command
+# substitutions terminate shell after 257 iterations'):
+# ------------ snip ------------
+# Recursive function+command substitutions
+# (e.g. func1() { x=$( func2 ) ; } ; x=$( func1 ) ) terminate the
+# ksh93 shell after 257 iterations with a exit code of "0" (it
+# seems the shell just "quits" after the last "return 0" statement
+# in the function).
+# Running the attached testcase terminates the shell after 257
+# iterations (g=257 in the script) while 256 iterations (replace
+# "257" with "256" in the script) just works fine.
+# The same testcase works Ok in ksh88 (=/usr/bin/ksh in
+# Solaris 10U5)
+#
+# Expected Result
+# The script should output "done" and return the exit code 0.
+#
+# Actual Result
+# No messsge. Exit code "0".
+#
+# Error Message(s)
+# None (exit code is "0").
+#
+# Test Case
+# f1()
+# {
+# h=$1
+# (( h=h-1 ))
+# (( h <= 0 )) && return 0
+# x=$(f1 "$h" "$l" "$g" d e "$l") || print -u2 "$g/$h: fail"
+# return 0
+# }
+# l=""
+# g=257
+# i=0
+# while (( i < $g )) ; do
+# l="${l}x"
+# (( i=i+1 ))
+# done
+# f1 "$g" "$l" "$g" d e "$l" || print -u2 "$g: fail0"
+# print "done"
+# exit 0
+#
+# Workaround
+# -
+# ------------ snip ------------
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+#
+# test1: Testcase from CR #6769332
+#
+(
+cat <<EOF
+# make sure we have enougth stack (needed for 64bit SPARC and SystemZ)
+ulimit -s 65536
+
+f1()
+{
+ h=\$1
+ (( h=h-1 ))
+ (( h <= 0 )) && return 0
+ x=\$(f1 "\$h" "\$l" "\$g" d e "\$l") || print -u2 "\$g/\$h: fail"
+ return 0
+}
+l=""
+g=257
+i=0
+while (( i < \$g )) ; do
+ l="\${l}x"
+ (( i=i+1 ))
+done
+f1 "\$g" "\$l" "\$g" d e "\$l" || print -u2 "\$g: fail0"
+print "done"
+EOF
+) | out="$( ${SHELL} 2>&1 ; )" || err_exit "Shell returned non-zero exit code $?."
+
+[[ "${out}" == "done" ]] || err_exit "Output expected to be 'done', got '${out}'."
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6777491_lacks_arithmetric_function_iszero.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6777491_lacks_arithmetric_function_iszero.sh
new file mode 100644
index 0000000000..2dd0fc997f
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6777491_lacks_arithmetric_function_iszero.sh
@@ -0,0 +1,95 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether the arithmetric function "iszero" is available.
+#
+# This was reported as CR #6777491 ("*ksh93* lacks arithmetric function
+# iszero()"):
+# ------------ snip ------------
+# ksh93 lacks arithmetric function "iszero()" which limits the ability
+# to classify floating-point values or even correctly match against
+# zero (since IEEE754-1985/2008 floating-point math differs between
+# positive and negaive zero values).
+# Frequency
+# Always
+# Regression
+# No
+# Steps to Reproduce
+# $ ksh93 -c '(( iszero(0) )) && print "0 is a zero"'
+# Expected Result
+# Output to stdout:
+# -- snip --
+# 0 is a zero
+# -- snip --
+# Actual Result
+# ksh93 exists with:
+# -- snip --
+# ksh93: iszero(0) : unknown function
+# -- snip --
+# Error Message(s)
+# ksh93: iszero(0) : unknown function
+# Test Case
+# ksh93 -c '(( iszero(0) )) && print "0 is a zero"'
+# ------------ snip ------------
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+typeset str
+integer i
+
+typeset -a tests=(
+ '(( iszero(0) )) && print "OK"'
+ '(( iszero(0.) )) && print "OK"'
+ '(( iszero(-0) )) && print "OK"'
+ '(( iszero(-0.) )) && print "OK"'
+ 'float n=0. ; (( iszero(n) )) && print "OK"'
+ 'float n=+0. ; (( iszero(n) )) && print "OK"'
+ 'float n=-0. ; (( iszero(n) )) && print "OK"'
+ 'float n=1. ; (( iszero(n) )) || print "OK"'
+ 'float n=1. ; (( iszero(n-1.) )) && print "OK"'
+ 'float n=-1. ; (( iszero(n+1.) )) && print "OK"'
+)
+
+for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ str="$( $SHELL -o errexit -c "${tests[i]}" 2>&1 )" || err_exit "test $i: returned non-zero exit code $?"
+ [[ "${str}" == "OK" ]] || err_exit "test $i: expected 'OK', got '${str}'"
+done
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6778077_sigthaw_trap.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6778077_sigthaw_trap.sh
new file mode 100644
index 0000000000..24f99cb581
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6778077_sigthaw_trap.sh
@@ -0,0 +1,83 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether ksh93 supports traps for the SIGTHAW
+# signal.
+#
+# This was reported as CR #6778077 ("*ksh93* does not understand "THAW"
+# as a signal for use with trap"):
+# -- snip --
+# While ksh93 understand THAW in the list of signals for kill it does
+# not understand it for "trap'
+#
+# : pod5.eu TS 6 $; kill -l | egrep '(THAW|FREEZE)'
+# FREEZE
+# THAW
+# : pod5.eu TS 7 $; trap "echo THAW" THAW
+# ksh93: trap: THAW: bad trap
+# : pod5.eu TS 8 $;
+#
+# Using the signal number (35) works around this.
+# -- snip --
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+
+## test one: Check whether the shell supports SIGTHAW as trap
+${SHELL} -o errexit -c 'trap "true" SIGTHAW ; true' || err_exit "SIGTHAW not supported."
+${SHELL} -o errexit -c 'trap "true" THAW ; true' || err_exit "THAW not supported."
+${SHELL} -o errexit -c 'trap "true" 35 ; true' || err_exit "signal 35 not supported."
+
+
+## test two: Check whether the shell supports SIGFREEZE as trap
+## (we check this since it is SIGTHAW's counterpart)
+${SHELL} -o errexit -c 'trap "true" SIGFREEZE ; true' || err_exit "SIGFREEZE not supported."
+${SHELL} -o errexit -c 'trap "true" FREEZE ; true' || err_exit "FREEZE not supported."
+${SHELL} -o errexit -c 'trap "true" 34 ; true' || err_exit "signal 34 not supported."
+
+
+## test three: Check all other signals listed by "kill -l"
+kill -l | while read i ; do
+ str="$( ${SHELL} -c "trap true $i ; print 'ok'" 2>&1 )" || err_exit "shell returned code $? for trap $i"
+ [[ "${str}" == "ok" ]] || err_exit "expected 'ok', got $str"
+done
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6789247_printf_hexfloat_rounding.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6789247_printf_hexfloat_rounding.sh
new file mode 100644
index 0000000000..69159a9f76
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6789247_printf_hexfloat_rounding.sh
@@ -0,0 +1,130 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether arithmetric math correctly supports
+# negative zero values
+#
+# This was reported as CR #6789247 ("libast/ksh93 1-digit hexfloat base conversion rounds incorrectly"):
+# ---- snip ----
+# Description
+# [The same issue was described in http://mail.opensolaris.org/pipermail/ksh93-integration-discuss/2008-December/006737.html]
+# This is basically a spin-off of http://bugs.opensolaris.org/view_bug.do?bug_id=6773712 ("1-digit hex fp
+# base conversion of long double rounds incorrectly").
+# The bug description for Solaris libc says this:
+# > The first line of output from this program is correct. The second line
+# > is not.
+# >
+# > leviathan% cat a.c
+# > #include <stdio.h>
+# >
+# > int main()
+# > {
+# > printf("%.0a\n", 1.5);
+# > printf("%.0La\n", 1.5L);
+# > return 0;
+# > }
+# > leviathan% cc -o a a.c
+# > leviathan% a
+# > 0x1p+1
+# > 0x1p+0
+# > leviathan%
+# If I compile the testcase with libast on Solaris 11/B84 SPARC (which
+# matches ast-open.2008-11-04) I get this:
+# -- snip --
+# $ cc -xc99=%all -I/usr/include/ast -last a.c -o a &&
+# ./a
+# 0x1p+00
+# 0x1p+00
+# -- snip --
+# ... which seems to be incorrect per the bugs comment above and should
+# be:
+# -- snip --
+# 0x1p+1
+# 0x1p+1
+# -- snip --
+# ksh93 has the same problem:
+# $ ksh93 -c 'float r=1.5 ; printf "%.0a\n" r'
+# 0x1p+00
+# Steps to Reproduce
+# Compile and run testcase like this:
+# -- snip --
+# $ cc -xc99=%all -I/usr/include/ast -last a.c -o a &&
+# ./a
+# -- snip --
+# Expected Result
+# 0x1p+1
+# 0x1p+1
+# Actual Result
+# 0x1p+00
+# 0x1p+00
+# ---- snip ----
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+
+float r
+float result
+typeset str
+
+# Test #001/a - check whether the result of a rounded 1.5 is 2.0
+r=1.5
+result=$(printf "%.0a\n" r) || err_exit "printf returned non-zero exit code"
+(( result == 2.0 )) || err_exit "result expected to be 2.0, got ${result}"
+
+
+# Test #001/b - same as test #001/a but uses "%.0A\n" instead of "%.0a\n"
+r=1.5
+result=$(printf "%.0A\n" r) || err_exit "printf returned non-zero exit code"
+(( result == 2.0 )) || err_exit "result expected to be 2.0, got ${result}"
+
+
+# Test #002/a - check whether the hexfloat string value matches the expected pattern
+r=1.5
+str=$(printf "%.0a\n" r) || err_exit "printf returned non-zero exit code"
+[[ "${str}" == ~(Glri)0x0*1p\+0*1 ]] || err_exit "str expected to match ~(Glri)0x0*1p\+0*1, got |${str}|"
+
+
+# Test #002/b - same as test #002/a but uses "%.0A\n" instead of "%.0a\n"
+r=1.5
+str=$(printf "%.0A\n" r) || err_exit "printf returned non-zero exit code"
+[[ "${str}" == ~(Glri)0x0*1p\+0*1 ]] || err_exit "str expected to match ~(Glri)0x0*1p\+0*1, got |${str}|"
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6800929_large_command_substitution_hang.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6800929_large_command_substitution_hang.sh
index 396095ee63..de745b8a3a 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6800929_large_command_substitution_hang.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6800929_large_command_substitution_hang.sh
@@ -35,7 +35,8 @@
#
# and here's where it's hung:
# ---8<---
-# xxxxx@xxxxx $ pstack 204600
+# Edward Pilatowicz <edward.pilatowicz@sun.com>
+# $ pstack 204600
# 204600: /bin/ksh /opt/onbld/bin/Install -o debug -k i86xpv -T domu-219:/tmp
# fffffd7fff2e3d1a write (1, 4154c0, 64)
# fffffd7ffefdafc8 sfwr () + 2d0
@@ -70,68 +71,142 @@
#
# as it turns out, i can easily reproduce this problem as follows:
# ---8<---
-# xxxxx@xxxxx $ ksh93
-# xxxxx@xxxxx $ set -- `cat /etc/termcap | sort | uniq`
+# $ ksh93
+# $ set -- `cat /etc/termcap | sort | uniq`
# <hang>
# ---8<---
# ---- snip ----
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
+set -o nounset
+Command=${0##*/}
integer Errors=0
-integer i j d
+# common functions/variables
+function isvalidpid
+{
+ kill -0 ${1} 2>/dev/null && return 0
+ return 1
+}
+integer testfilesize i maxwait
typeset tmpfile
+integer testid
+
# test 1: run loop and check various temp filesizes
tmpfile="$(mktemp "/tmp/sun_solaris_cr_6800929_large_command_substitution_hang.${PPID}.$$.XXXXXX")" || err_exit "Cannot create temporary file."
-for (( i=1*1024 ; i <= 512*1024 ; i*=2 )) ; do
+compound -a testcases=(
+ # test 1a: Run test child for $(...)
+ # (note the pipe chain has to end in a builtin command, an external command may not trigger the bug)
+ ( name="test1a" cmd="builtin cat ; print -- \"\$(cat \"${tmpfile}\" | cat)\" ; true" )
+ # test 1b: Same as test1a but uses ${... ; } instead if $(...)
+ ( name="test1b" cmd="builtin cat ; print -- \"\${ cat \"${tmpfile}\" | cat ; }\" ; true" )
+ # test 1c: Same as test1a but does not use a pipe
+ ( name="test1c" cmd="builtin cat ; print -- \"\$(cat \"${tmpfile}\" ; true)\" ; true" )
+ # test 1d: Same as test1a but does not use a pipe
+ ( name="test1d" cmd="builtin cat ; print -- \"\${ cat \"${tmpfile}\" ; true ; }\" ; true" )
+
+ # test 1e: Same as test1a but uses an external "cat" command
+ ( name="test1e" cmd="builtin -d cat /bin/cat ; print -- \"\$(cat \"${tmpfile}\" | cat)\" ; true" )
+ # test 1f: Same as test1a but uses an external "cat" command
+ ( name="test1f" cmd="builtin -d cat /bin/cat ; print -- \"\${ cat \"${tmpfile}\" | cat ; }\" ; true" )
+ # test 1g: Same as test1a but uses an external "cat" command
+ ( name="test1g" cmd="builtin -d cat /bin/cat ; print -- \"\$(cat \"${tmpfile}\" ; true)\" ; true" )
+ # test 1h: Same as test1a but uses an external "cat" command
+ ( name="test1h" cmd="builtin -d cat /bin/cat ; print -- \"\${ cat \"${tmpfile}\" ; true ; }\" ; true" )
+)
+
+for (( testfilesize=1*1024 ; testfilesize <= 1024*1024 ; testfilesize*=2 )) ; do
# Create temp file
{
- for ((j=0 ; j < i ; j+=16 )) ; do
- print "0123456789abcde"
+ for (( i=0 ; i < testfilesize ; i+=64 )) ; do
+ print "0123456789abcdef01234567890ABCDEF0123456789abcdef01234567890ABCDE"
done
} >"${tmpfile}"
-
- # Run test child
- ${SHELL} -c "builtin cat ; print -- \"\$(cat \"${tmpfile}\" | cat)\" ; true" >/dev/null &
- (( childpid=$! ))
# wait up to log2(i) seconds for the child to terminate
# (this is 10 seconds for 1KB and 19 seconds for 512KB)
- (( d=log2(i) ))
- for (( j=0 ; j < d ; j++ )) ; do
- kill -0 ${childpid} 2>/dev/null || break
- sleep 0.5
+ (( maxwait=log2(testfilesize) ))
+
+ for testid in "${!testcases[@]}" ; do
+ nameref currtst=testcases[testid]
+ ${SHELL} -o errexit -c "${currtst.cmd}" >"${tmpfile}.out" &
+ (( childpid=$! ))
+
+ for (( i=0 ; i < maxwait ; i++ )) ; do
+ isvalidpid ${childpid} || break
+ sleep 0.25
+ done
+
+ if isvalidpid ${childpid} ; then
+ err_exit "${currtst.name}: child (pid=${childpid}) still busy, filesize=${testfilesize}."
+ kill -KILL ${childpid} 2>/dev/null
+ fi
+ wait || err_exit "${currtst.name}: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime)
+
+ # compare input/output
+ cmp -s "${tmpfile}" "${tmpfile}.out" || err_exit "${currtst.name}: ${tmpfile} and ${tmpfile}.out differ, filesize=${testfilesize}."
+ rm "${tmpfile}.out"
done
- if kill -0 ${childpid} 2>/dev/null ; then
- err_exit "test1: child (pid=${childpid}) still busy, filesize=${i}."
- kill -KILL ${childpid} 2>/dev/null
- fi
- wait # wait for child (and/or avoid zombies/slime)
+ # Cleanup
rm "${tmpfile}"
done
-# test 2: Edward's Solaris-specific testcase
-${SHELL} -c 'builtin uniq ; set -- `cat /etc/termcap | sort | uniq` ; true' >/dev/null &
+# test 2a: Edward Pilatowicz <edward.pilatowicz@sun.com>'s Solaris-specific testcase
+${SHELL} -o errexit -c 'builtin uniq ; set -- `cat /etc/termcap | sort | uniq` ; true' >/dev/null &
(( childpid=$! ))
sleep 5
-if kill -0 ${childpid} 2>/dev/null ; then
- err_exit "test2: child (pid=${childpid}) still busy."
+if isvalidpid ${childpid} ; then
+ err_exit "test2a: child (pid=${childpid}) still busy."
kill -KILL ${childpid} 2>/dev/null
fi
-wait # wait for child (and/or avoid zombies/slime)
+wait || err_exit "test2a: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime)
+
+
+# test 2b: Same as test 2a but uses ${... ; } instead of $(...)
+${SHELL} -o errexit -c 'builtin uniq ; set -- ${ cat /etc/termcap | sort | uniq ; } ; true' >/dev/null &
+(( childpid=$! ))
+sleep 5
+if isvalidpid ${childpid} ; then
+ err_exit "test2b: child (pid=${childpid}) still busy."
+ kill -KILL ${childpid} 2>/dev/null
+fi
+wait || err_exit "test2b: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime)
+
+
+# test 2c: Same as test 2a but makes sure that "uniq" is not a builtin
+${SHELL} -o errexit -c 'builtin -d uniq /bin/uniq ; set -- `cat /etc/termcap | sort | uniq` ; true' >/dev/null &
+(( childpid=$! ))
+sleep 5
+if isvalidpid ${childpid} ; then
+ err_exit "test2c: child (pid=${childpid}) still busy."
+ kill -KILL ${childpid} 2>/dev/null
+fi
+wait || err_exit "test2c: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime)
+
+
+# test 2d: Same as test 2c but uses ${... ; } instead of $(...)
+${SHELL} -o errexit -c 'builtin -d uniq /bin/uniq ; set -- ${ cat /etc/termcap | sort | uniq ; } ; true' >/dev/null &
+(( childpid=$! ))
+sleep 5
+if isvalidpid ${childpid} ; then
+ err_exit "test2d: child (pid=${childpid}) still busy."
+ kill -KILL ${childpid} 2>/dev/null
+fi
+wait || err_exit "test2d: Child returned non-zero exit code." # wait for child (and/or avoid zombies/slime)
+
# tests done
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6805792_varmovetest1.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6805792_varmovetest1.sh
new file mode 100644
index 0000000000..4f774b2f8b
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6805792_varmovetest1.sh
@@ -0,0 +1,152 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether "typeset -m" correctly moves local variables
+# into a global variable tree.
+#
+# This was reported as CR #6805792 ("XXXX"):
+# -------- snip --------
+# The following attempt to move a local node into an associative array
+# fails like this:
+# -- snip --
+# typeset -C tree
+# function f1
+# {
+# nameref tr=$1
+#
+# typeset -A tr.subtree
+#
+# typeset -C node
+#
+# node.one="hello"
+# node.two="world"
+#
+# # move local note into the array
+# typeset -m tr.subtree["a_node"]=node
+#
+# return 0
+# }
+# f1 tree
+# printf "%B\n" tree
+# print "ok"
+# exit 0
+# -- snip --
+# The output looks like this:
+# -- snip --
+# $ ksh93
+# varmovetest1.sh
+# (
+# (
+# )
+# ok
+# -- snip --
+# ... but AFAIK it should print:
+# -- snip --
+# (
+# typeset -A subtree=(
+# [a_node]=(
+# one=hello
+# two=world
+# )
+# )
+# )
+# ok
+# -- snip --
+# -------- snip --------
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+
+## test start
+compound tree1 tree2
+
+# add node to tree which uses "typeset -m" to move a local variable
+# into tree1.subtree["a_node"]
+function f1
+{
+ nameref tr=$1
+
+ typeset -A tr.subtree
+
+ compound node
+
+ node.one="dummy1"
+ node.two="dummy2"
+
+ # We use the nameref's here since ast-ksh,2008-12-12 crashes
+ # when this function returns because "nodeone" and "nodetwo"
+ # still reference "node" which was renamed.
+ # (note that "f1" must be first function and the first being
+ # called, otherwise the crash will not occur)
+ nameref nodeone=node.one
+ nameref nodetwo=node.two
+ nodeone="hello"
+ nodetwo="world"
+
+ # move local note into the array
+ typeset -m tr.subtree["a_node"]=node
+
+ return 0
+}
+
+# Alternative version which uses "nameref" instead of "typeset -m"
+function f2
+{
+ nameref tr=$1
+
+ typeset -A tr.subtree
+
+ nameref node=tr.subtree["a_node"]
+
+ node.one="hello"
+ node.two="world"
+
+ return 0
+}
+
+f1 tree1
+f2 tree2
+
+[[ "${tree1.subtree["a_node"].one}" == "hello" ]] || err_exit "Expected tree1.subtree[\"a_node\"].one == 'hello', got ${tree1.subtree["a_node"].one}"
+[[ "${tree1.subtree["a_node"].two}" == "world" ]] || err_exit "Expected tree1.subtree[\"a_node\"].two == 'world', got ${tree1.subtree["a_node"].two}"
+[[ "${tree1}" == "${tree2}" ]] || err_exit "tree1 and tree2 differ:"$'\n'"$(diff -u <( printf '%B\n' tree1 ) <( printf '%B\n' tree2 ) )"
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6805794_character_to_wchar_not_working.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6805794_character_to_wchar_not_working.sh
new file mode 100644
index 0000000000..bbcb9b168d
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6805794_character_to_wchar_not_working.sh
@@ -0,0 +1,106 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether arithmetric operator '<character>
+# is working
+#
+# This was reported as CR #6805794 ('[ku1] printf returns "invalid character constant" for $ printf "%d\n" "'<euro>"'):
+# ------------ snip ------------
+# There seems be a bug in how ast-ksh.2008-11-04's "printf" builtin
+# handles multibyte characters. For example if I try this in the
+# en_US.UTF-8 locale ("<euro>" needs to be replace with the EURO symbol):
+# -- snip --
+# $ printf "%d\n" "'<euro>"
+# -ksh93: printf: warning: ': invalid character constant
+# 226
+# -- snip --
+# AFAIK the correct behaviour was to return the numeric value of the
+# <euro> symbol in this case (hexadecimal "20ac", decimal 8364), e.g.
+# -- snip --
+# $ printf "%d\n"
+# "'<euro>"
+# 8364
+# -- snip --
+# Frequency
+# Always
+# Regression
+# No
+# Steps to Reproduce
+# Enter this in an interractive shell:
+# $ printf "%d\n" "'<euro>"
+# Expected Result
+# -- snip --
+# $ printf "%d\n"
+# "'<euro>"
+# 8364
+# -- snip --
+# Actual Result
+# -- snip --
+# $ printf "%d\n" "'<euro>"
+# -ksh93: printf: warning: ': invalid character constant
+# 226
+# -- snip --
+# Error Message(s)
+# printf: warning: ': invalid character constant
+# Test Case
+# printf "%d\n" "'<euro>"
+# Workaround
+# None.
+# ------------ snip ------------
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+
+# declare variables
+typeset str
+
+# test whether the locale uses an UTF-8 (-like) encoding and override it on demand
+[[ "$(printf "\u[20ac]")" == $'\342\202\254' ]] || LC_ALL=en_US.UTF-8
+if [[ "$(printf "\u[20ac]")" != $'\342\202\254' ]] ; then
+ err_exit "Local overrride failed."
+ exit $((Errors))
+fi
+
+# run test
+str=$(print $'printf "%d\\\\n" "\'\342\202\254"' | source /dev/stdin)
+[[ "${str}" == "8364" ]] || err_exit "expected 8364, got ${str}"
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6805795_negative_zero.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6805795_negative_zero.sh
new file mode 100644
index 0000000000..1dccc97505
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6805795_negative_zero.sh
@@ -0,0 +1,170 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether arithmetric math correctly supports
+# negative zero values
+#
+# This was reported as CR #6805795 ("[ku1] ksh93 does not differ between -0 and +0"):
+# ------------ snip ------------
+# Original bug report was:
+# ------ snip ------
+# Is there a reason why ksh93 does not display the negative sign for the
+# value zero ? For example if I have use the C99 function "copysign"
+# (copies absolute value of operant a and sign of operant b) I get this
+# for { a=5, b=-0 }:
+# -- snip --
+# $ ksh93 -c 'float x; (( x=copysign(5, -0) )) ; printf "%f\n"
+# x'
+# -5.000000
+# -- snip --
+# Now if I swap operands a and b I get this result:
+# -- snip --
+# $ ksh93 -c 'float x; (( x=copysign(0, -5) )) ; printf "%f\n" x'
+# 0.000000
+# -- snip --
+# AFAIK this result should be "-0.000000" ... or not ?
+# BTW: Parsing of "-0" doesn't seem to work either, e.g.
+# -- snip --
+# $ ksh93 -c 'float x a=-1 b=-0; (( x=copysign(a, b) )) ; printf "%f\n"
+# x'
+# 1.000000
+# -- snip --
+# ... while AFAIK it should be "-1.000000" since the 2nd operand of
+# "copysign" defines the sign of the result.
+# ------ snip ------
+# ------------ snip ------------
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+typeset str
+
+# test 1: test "copysign()" using constant values
+str=$(
+ set -o errexit
+
+ print -- $(( copysign(0, -5) ))
+ ) || err_exit "test failed."
+[[ "${str}" == "-0" ]] || err_exit "Expected copysign(0, -5) == -0, got ${str}"
+
+
+# test 2: Same as test 1 but using variables for the values
+str=$(
+ set -o errexit
+
+ float a
+ float b
+ float c
+
+ a=0.
+ b=-5.
+
+ (( c=copysign(a, b) ))
+
+ print -- "$c"
+ ) || err_exit "test failed."
+[[ "${str}" == "-0" ]] || err_exit "Expected c == -0, got ${str}"
+
+
+# test 3: test "signbit()"
+str=$(
+ set -o errexit
+
+ float a
+
+ a=-0.
+
+ print -- $(( signbit(a) ))
+ ) || err_exit "test failed."
+[[ "${str}" == "1" ]] || err_exit "Expected signbit(a, b) == 1, got ${str}"
+
+
+# test 4: test "signbit()"
+str=$(
+ set -o errexit
+
+ float a
+ float c
+
+ a=-0.
+
+ (( c=signbit(a) ))
+
+ print -- "$c"
+ ) || err_exit "test failed."
+[[ "${str}" == "1" ]] || err_exit "Expected c == 1, got ${str}"
+
+
+# test 5: test whether "typeset -X" (C99 "hexfloat") correctly recognizes
+# negative zero assigned from a "float"
+str=$(
+ set -o errexit
+
+ float a # float
+ typeset -X c # hexfloat
+
+ a=-0.
+
+ # copy value from "float" to "hexfloat"
+ (( c=a ))
+
+ print -- "$c"
+ ) || err_exit "test failed."
+[[ "${str}" == -0x* ]] || err_exit "Expected c == -0x*, got ${str}"
+
+
+# test 6: Reverse of test 5: Test whether "float" correctly recognizes
+# a C99 "hexfloat" value
+str=$(
+ set -o errexit
+
+ typeset -X a # hexfloat
+ float c # float
+
+ a=-0x0.0000000000000000000000000000p+00
+
+ # copy value from "hexfloat" to "float"
+ (( c=a ))
+
+ print -- "$c"
+ ) || err_exit "test failed."
+[[ "${str}" == "-0" ]] || err_exit "Expected c == -0, got ${str}"
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6835835_builtin_cat_n_broken.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6835835_builtin_cat_n_broken.sh
new file mode 100644
index 0000000000..dc91bbeb82
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6835835_builtin_cat_n_broken.sh
@@ -0,0 +1,139 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether ksh93's builtin "cat" command properly
+# supports the "-n" option.
+#
+# This was reported as CR #6835835 ('ksh93 "cat" builtin does not handle "-n" correctly'):
+# ------------ snip ------------
+# [Originally reported in
+# http://mail.opensolaris.org/pipermail/ksh93-integration-discuss/2009-February/007050.html
+# by Casper Dik]
+# -- snip --
+# I just noticed this in ksh93:
+# ksh93 -c 'yes "" | head -5|cat -n'
+# 1
+# 2
+# 3
+# 4
+# (I used this for older shells when I want to a list of all integers from 1
+# to a particular number)
+# -- snip --
+# Frequency
+# Always
+# Regression
+# No
+# Steps to Reproduce
+# Execute $ ksh93 -c 'yes "" | head -5|cat -n' #
+# Expected Result
+# 1
+# 2
+# 3
+# 4
+# 5
+# Actual Result
+#
+#
+# 1
+# 2
+#
+# 3
+#
+# 4
+# Error Message(s)
+# None.
+# Test Case
+# See description.
+# Workaround
+# Disable ksh93's builtin "cat" command either via using an absolute path
+# to the "cat" command (POSIX-style workaround) or using ksh93's
+# "builtin" command to remove "cat" from the list of builtin
+# commands (e.g. $ builtin -d /bin/cat /usr/bin/cat #).
+# ------------ snip ------------
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+#
+# test 1: Compare output of various "cat -n" combinations
+#
+integer i
+typeset expected_output
+typeset out
+
+expected_output=$( ${SHELL} -c 'for ((i=1 ; i <= 12 ; i++ )) ; do printf "%6d\t\n" i ; done' )
+
+compound -a testcases=(
+ # note: we have to add an extra /usr/bin/cat at the end of the pipe to make
+ # sure the "cat" builtin uses the correct buffering mode to trigger
+ # the error and a "true" to make sure the "cat" command isn't the last command
+ # of the shell
+ ( name="test1a" cmd='integer i ; builtin cat ; for ((i=1 ; i <= 12 ; i++ )) ; do print ; done | cat -n | /usr/bin/cat ; true' )
+ # same as "test1a" but uses external "cat" command
+ ( name="test1b" cmd='integer i ; for ((i=1 ; i <= 12 ; i++ )) ; do print ; done | /usr/bin/cat -n | /usr/bin/cat ; true' )
+
+ # same as "test1a" but without the last /usr/bin/cat in the pipe
+ ( name="test1c" cmd='integer i ; builtin cat ; for ((i=1 ; i <= 12 ; i++ )) ; do print ; done | cat -n ; true' )
+ # same as "test1b" but without the last /usr/bin/cat in the pipe
+ ( name="test1d" cmd='integer i ; for ((i=1 ; i <= 12 ; i++ )) ; do print ; done | /usr/bin/cat -n ; true' )
+)
+
+for testid in "${!testcases[@]}" ; do
+ nameref tc=testcases[${testid}]
+
+ out="$( ${SHELL} -o errexit -c "${tc.cmd}" )" || err_exit "${tc.name}: Shell failed"
+ [[ "${expected_output}" == "${out}" ]] || err_exit "${tc.name}: Builtin output does not match expected output"
+
+ out="$( ${SHELL} +o errexit -c "${tc.cmd}" )" || err_exit "${tc.name}: Shell failed"
+ [[ "${expected_output}" == "${out}" ]] || err_exit "${tc.name}: Builtin output does not match expected output"
+done
+
+
+#
+# test 2: Casper Dik's original testcase
+# from http://mail.opensolaris.org/pipermail/ksh93-integration-discuss/2009-February/007050.html
+#
+
+cmp -s \
+ <( ${SHELL} -c 'yes "" | head -5 | cat -n' ) \
+ <( for ((i=1 ; i <= 5 ; i++ )) ; do printf "%6d\t\n" i ; done ) \
+ || err_exit 'yes "" | head -5 | cat -n does not match expected output.'
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6848486_echo_test_with_test_undefined_executes_test_builtin.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6848486_echo_test_with_test_undefined_executes_test_builtin.sh
new file mode 100644
index 0000000000..396816960a
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6848486_echo_test_with_test_undefined_executes_test_builtin.sh
@@ -0,0 +1,94 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether ksh93 does not execute builtin command
+# "foo" when referencing variable "foo" when the variable is not
+# set (this applies to all builtin commands not bound to a
+# specific PATH element, e.g. "test", "sleep", "print" etc.).
+#
+# This was reported as CR #6848486 ('"echo ${test}" with test
+# undefined crashes the shell')
+# ------------ snip ------------
+# This is an odd one:
+#
+# $ ksh93 --version
+# version sh (AT&T Research) 93t 2008-11-04
+# $ ksh93
+# jl138328@gir:~$ echo $test
+#
+# jl138328@gir:~$ echo ${test}
+# Segmentation Fault (core dumped)
+# ------------ snip ------------
+#
+# The bug originates from the ksh93 "type system" which allows
+# an application to define it's own types in ksh93. In such cases
+# the output of function "mytype.len" is used when type "mytype"
+# has no member variable "len" (note it requires the use of
+# ${foo} since the use of $foo does not allow "foo" to contain
+# a dot in the variable name).
+# The implementation in ast-ksh.2009-11-04 however does this
+# for _all_ types of variables and not only for those which
+# are a member of an application-defined type, therefore
+# causing this bug.
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+
+# Test 1: Test whether the shell crashes when looking for an empty
+# "shell" variable.
+# (note: return code 78 was just picked randomly)
+$SHELL -c 'unset test ; print ${test} ; exit 78' >/dev/null 2>&1
+(( $? == 78 )) || err_exit "expected return code is 78, got $?"
+
+
+# Test 2: Test whether the shell can reach a point (which prints
+# "#mark") after the use of ${test} in the script.
+out=$($SHELL -o errexit -c 'unset test ; print ${test} ; print "#mark"' 2>&1 ) || err_exit "Shell returned error code $?, expected 0."
+[[ "$out" == $'\n#mark' ]] || err_exit "Expected output \$'\n#mark', got '${out}'"
+
+
+# Test 3: Check whether the use of ${sleep} returns nothing
+# (ast-ksh.2008-11-04 will return the usage string of the sleep
+# builtin)
+out=$($SHELL -o errexit -c 'print ${sleep} ; print "#mark"' 2>&1 ) || err_exit "Shell returned error code $?, expected 0."
+[[ "$out" == $'\n#mark' ]] || err_exit "Expected output \$'\n#mark', got '${out}'"
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6855875_typeset_hexfloat_has_too_few_digits.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6855875_typeset_hexfloat_has_too_few_digits.sh
new file mode 100644
index 0000000000..22de05b56c
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6855875_typeset_hexfloat_has_too_few_digits.sh
@@ -0,0 +1,145 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether arithmetric math correctly
+# converts a IEEE 754-2008 floating-point value to the C99 hexfloat format
+# and back _without_ using digits.
+#
+# This was reported as CR #6855875 ("typeset -X x ; print $x # does not
+# print sufficient digits to restore value"):
+# ------------ snip ------------
+# $ typeset -X varname # was added to ksh93 to get a reliable way
+# (using the C99 "hexfloat" format (see printf(3c)'s "%a" format)) to
+# serialise a IEEE754-2008 floating-point value to a string and later feed
+# it back into a application _without_ loosing any precision (normal
+# base10 floating-point values (e.g. used by $ typeset -E/-F-G #) cause
+# rounding errors since IEEE754-2008 |long double| uses base2).
+# However $ typeset -l -X x ; ... ; print $x # currently does not print
+# sufficient number of digits to restore the full |long double| value as
+# expected, instead some digits are missing, resulting in an unwanted
+# rounding.
+# Example:
+# -- snip --
+# $ ksh93 -c 'typeset -l -X y y_ascii; (( y=sin(90) )) ; y_ascii=$y ; (( y
+# == y_ascii )) || print "no match,\n\t$(printf "%a\n" y)\n!=\n\t$(printf
+# "%a\n" y_ascii)"'
+# no match,
+# 0x1.c9b9ee41cb8665c7890a136ace6bp-01
+# !=
+# 0x1.c9b9ee41cc000000000000000000p-01
+# -- snip --
+# Frequency
+# Always
+# Regression
+# No
+# Steps to Reproduce
+# [See description]
+# Expected Result
+# [See description]
+# Actual Result
+# [See description]
+# Error Message(s)
+# -
+# Test Case
+# typeset -l -X y y_ascii
+# (( y=sin(90) ))
+# y_ascii=$y # convert y to string and store it in "y_ascii"
+# if (( y == y_ascii )) ; then
+# print "no match,\n\t$(printf "%a\n" y)\n!=\n\t$(printf "%a\n"
+# y_ascii)"
+# fi
+# Workaround
+# 1. Manually increase the number of digits via typeset
+# -X<numdigits>
+# OR
+# 2. Use $ printf "%a" varname #
+# ------------ snip ------------
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+
+# declare variables
+typeset str
+integer i
+float x
+float -a test_values
+
+typeset -l -X y # hexfloat
+typeset -l -E y_restored1
+typeset -l -F y_restored2
+typeset -l -X y_restored3
+
+
+# create array of test values
+for (( x=-181. ; x < 361. ; x+=.1 )) ; do
+ test_values+=( x )
+done
+test_values+=( 0 -0 +0 ) # (nan -nan inf -inf) are excluded since nan!=nan is always "true"
+
+
+# run the tests
+for (( i=0 ; i < ${#test_values[@]} ; i++ )) ; do
+ (( y=sin(test_values[i]) ))
+
+ # convert floating-point value to string (using the hexfloat format) and store it in "str"
+ str="${y}"
+
+ # convert it back (via string assignment)
+ y_restored1="${str}"
+ y_restored2="${str}"
+ y_restored3="${str}"
+ (( y == y_restored1 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored1)"
+ (( y == y_restored2 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored2)"
+ (( y == y_restored3 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored3)"
+
+ # convert it back (using arithmetric expression)
+ (( y_restored1=str ))
+ (( y_restored2=str ))
+ (( y_restored3=str ))
+ (( y == y_restored1 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored1)"
+ (( y == y_restored2 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored2)"
+ (( y == y_restored3 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored3)"
+
+ # we exit if we get more than 8 errors (126 would be the maximum)
+ (( Errors > 8 )) && exit $((Errors))
+done
+
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6862121_shbinexec_kernel_module_defunct.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6862121_shbinexec_kernel_module_defunct.sh
new file mode 100644
index 0000000000..568b43f35d
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6862121_shbinexec_kernel_module_defunct.sh
@@ -0,0 +1,111 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether the Solaris kernel can directly execute compiled
+# shell code.
+#
+# This was reported as CR #6862121 ("shbinexec kernel module defunct"):
+# ------------ snip ------------
+# [Originally reported by Sun Japan]
+# The new shbinexec kernel module added in B106 is defunct, originally
+# caused by my mismerge of the original development tree and later
+# because the matching test module didn't test it correctly (April
+# quickly discovered the problem but the issue drowned in the cleanup
+# putbacks ).
+# Frequency
+# Always
+# Regression
+# No
+# Steps to Reproduce
+# $ cat test1.sh
+# print hello
+# printf "args=%s\n" "$@"
+# $ shcomp test1.sh test1
+# # note: this MUST be bash since ksh93 has special support for compiled shell
+# # scripts which causes the kernel module to be bypassed (that's why the tes
+# # never worked)
+# $ bash -c './test1 "a b" "c" "d"'
+# Expected Result
+# hello
+# args=a a1
+# args=b
+# args=c
+# Actual Result
+# ./test1: line 1: a: not found
+# Error Message(s)
+# ./test1: line 1: a: not found
+# Test Case
+# See above.
+# ------------ snip ------------
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+typeset ocwd
+typeset tmpdir
+typeset out
+
+# create temporary test directory
+ocwd="$PWD"
+tmpdir="$(mktemp -d "test_sun_solaris_cr_6862121_shbinexec_kernel_module_defunct.XXXXXXXX")" || err_exit "Cannot create temporary directory"
+
+cd "${tmpdir}" || err_exit "cd ${tmpdir} failed."
+
+
+# run tests
+{
+cat <<EOF
+ print hello
+ printf "args=%s\n" "\$@"
+EOF
+} >script1.sh
+
+# Compile script (note we use the platform's /usr/bin/shcomp, _not_ ${SHCOMP})
+/usr/bin/shcomp "script1.sh" "script1" || err_exit "shcomp failed with error=$?"
+
+[[ -x "./script1" ]] || err_exit "Script script1 not executable"
+out="$(/usr/bin/bash -c './script1 a b "c d"' 2>&1 )" || err_exit "Compiled script failed to execute, error=$?"
+[[ "${out}" == $'hello\nargs=a\nargs=b\nargs=c d' ]] || err_exit "Expected xxx, got $(printf "%q\n" "$out")"
+
+# cleanup
+rm "script1" "script1.sh"
+cd "${ocwd}"
+rmdir "${tmpdir}" || err_exit "Cannot remove temporary directory ${tmpdir}".
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6881017_background_process_in_subshell_hangs_caller.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6881017_background_process_in_subshell_hangs_caller.sh
new file mode 100644
index 0000000000..a5aae41ce5
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6881017_background_process_in_subshell_hangs_caller.sh
@@ -0,0 +1,82 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether a background process called in a subshell can
+# cause it to wait for the child process instead of exiting.
+#
+# This was reported as CR #6881017 ("Subshell doesn't exit, holds pipe
+# open preventing callers from exiting"):
+# ------------ snip ------------
+# The following scenario hangs with snv_122, 100% reproducible:
+#
+# Create a script hangit:
+# -----
+# #!/bin/ksh
+# ( sleep 100000 </dev/null >/dev/null 2>&1 & )
+# exit 0
+# -----
+#
+# Run the following command:
+# hangit | tee -a /tmp/log
+#
+# The hang can be eliminated either by removing the "exit 0" line (?!?), or by
+# redirecting the subshell output to /dev/null.
+#
+# This is pretty nasty. I've whittled it down to this simple case but am seeing
+# it in a much more subtle and complex environment where there are several
+# intermediate calling scripts which have exited and eventually the parent pipes
+# the output and hangs on the open pipe. It was hard to track down.
+# ------------ snip ------------
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+float tstart tstop tdiff
+
+# run test with 10 second timeout
+(( tstart=SECONDS ))
+$SHELL -c '( sleep 10 </dev/null >/dev/null 2>&1 & ) ; exit 0' | cat >/dev/null
+(( tstop=SECONDS ))
+
+# we remove two seconds below to make sure we don't run into issues
+# with smaller xntpd adjustments
+(( tdiff=tstop-tstart ))
+(( tdiff < (10.-2.) )) || err_exit "test run needed ${tdiff} seconds to complete (instead of < 8.)"
+
+# tests done
+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
index 2089ad184c..8e1e2ab937 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_getconf.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_getconf.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -38,6 +38,7 @@ function err_exit
}
alias err_exit='err_exit $LINENO'
+set -o nounset
Command=${0##*/}
integer Errors=0
@@ -56,6 +57,15 @@ export PATH=/usr/bin:/bin
# work in compiled shell scripts)
typeset -r getconf_test_functions="$(
cat <<EOF
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r \${Command}[\$1]: "\${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit \$LINENO'
+Command=\${0##*/}
+integer Errors=0
# compare builtin getconf output with /usr/bin/getconf
function compare_normal
{
@@ -63,13 +73,13 @@ function compare_normal
/usr/bin/getconf -a |
while read i ; do
(( getconf_keys++ ))
- t="${i%:*}"
+ t="\${i%:*}"
- a="$(getconf "$t" 2>/dev/null)"
- b="$(/usr/bin/getconf "$t" 2>/dev/null)"
+ 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|"
+ if [[ "\$a" != "\$b" ]] ; then
+ print -u2 "getconf/normal built mismatch: |\$t|:|\$a| != |\$b|"
(( mismatch++ ))
fi
done
@@ -82,13 +92,13 @@ function compare_path
/usr/bin/getconf -a |
while read i ; do
(( getconf_keys++ ))
- t="${i%:*}"
+ t="\${i%:*}"
- a="$(getconf "$t" "/tmp" 2>/dev/null)"
- b="$(/usr/bin/getconf "$t" "/tmp" 2>/dev/null)"
+ 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|"
+ if [[ "\$a" != "\$b" ]] ; then
+ print -u2 "getconf/path built mismatch: |\$t|:|\$a| != |\$b|"
(( mismatch++ ))
fi
done
@@ -108,7 +118,7 @@ do
export PATH="${i}"
## test whether the getconf builtin is available
- if [[ "$(builtin | fgrep "/bin/getconf")" = "" ]] ; then
+ if [[ "$(builtin | fgrep "/bin/getconf")" == "" ]] ; then
err_exit '/bin/getconf not found in the list of builtins.'
fi
@@ -161,5 +171,6 @@ do
(( Errors+=$? ))
done
+
# tests done
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_local_compound_nameref001.sh b/usr/src/lib/libshell/common/tests/sun_solaris_local_compound_nameref001.sh
index 30a2deb314..e95a502daf 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_local_compound_nameref001.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_local_compound_nameref001.sh
@@ -28,17 +28,20 @@
# name reference test #001
#
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
+set -o nounset
+Command=${0##*/}
integer Errors=0
+
function function2
{
nameref v=$1
@@ -60,5 +63,6 @@ x="$(function1)"
[[ "$x" != 'x=19, y=20' ]] && err_exit "expected 'x=19, y=20', got '${x}'"
+
# tests done
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_staticvariables.sh b/usr/src/lib/libshell/common/tests/sun_solaris_staticvariables.sh
index 9230c9925f..9f430d7c1c 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_staticvariables.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_staticvariables.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -45,8 +45,11 @@ function testfunc
alias testfunc='testfunc $LINENO'
alias err_exit='err_exit2 $LINENO'
+set -o nounset
+Command=${0##*/}
integer Errors=0
+
# string
testfunc '(function l { typeset -S x ; x+="#" ; $1 && print "$x" ; } ; l false ; l false ; l true)' "###"
testfunc 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false ; l false ; l true' ">###"
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_vartree001.sh b/usr/src/lib/libshell/common/tests/sun_solaris_vartree001.sh
index 74783e6ff7..bf5257a78a 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_vartree001.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_vartree001.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -50,15 +50,17 @@
# [14] main(argc = 2, argv = 0xffffffff7ffffa08), line 46 in "pmain.c"
#
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
+# the test cannot use "nounset"
+Command=${0##*/}
integer Errors=0
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_vartree002.sh b/usr/src/lib/libshell/common/tests/sun_solaris_vartree002.sh
index e233f596e3..c2ca8f5e5e 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_vartree002.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_vartree002.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -31,22 +31,24 @@
# and "unset" handling.
#
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
+# the test cannot use "nounset"
+Command=${0##*/}
integer Errors=0
# "built_tree1" and "built_tree2" are identical except the way how they test
# whether a variable exists:
# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable
# as non-zero length content
-# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell
+# - "built_tree2" uses "! ([[ -v varname ]] ; res=$? ; unset varname ; exit $res)", e.g. "unset" in a subshell.
function build_tree1
{
#set -o errexit -o xtrace
@@ -113,7 +115,7 @@ function build_tree1
# whether a variable exists:
# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable
# as non-zero length content
-# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell
+# - "built_tree2" uses "! ([[ -v varname ]] ; res=$? ; unset varname ; exit $res)", e.g. "unset" in a subshell.
function build_tree2
{
#set -o errexit -o xtrace
@@ -144,12 +146,12 @@ function build_tree2
[[ "$c" == "" ]] && c='-'
#if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
- if ! (unset dest_tree.l1["$a"]) ; then
+ if ! ([[ -v dest_tree.l1["$a"] ]] ; res=$? ; unset dest_tree.l1["$a"] ; exit $res) ; then
typeset -A dest_tree.l1["$a"].l2
fi
#if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then
- if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then
+ if ! ([[ -v dest_tree.l1["$a"].l2["$b"] ]] ; res=$? ; unset dest_tree.l1["$a"].l2["$b"] ; exit $res) ; then
typeset -A dest_tree.l1["$a"].l2["$b"].l3
fi
@@ -301,43 +303,47 @@ function main
#### test "unset" in a subshell
- ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \
+ ( [[ -v 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ]] ; res=$? ; unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ; exit $res ) || \
err_exit "Try 1: Variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found."
- ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \
+ ( [[ -v 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ]] ; res=$? ; unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ; exit $res ) || \
err_exit "Try 2: Variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found."
# remove parent node (array element) and then check whether the child is gone, too:
(
set -o errexit
unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]'
- ! unset 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'
+ ! [[ -v 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
) || err_exit "Global: Parent node removed (array element), child still exists"
(
set -o errexit
unset 'mytree_local1.l1[urw].l2[itc zapfdingbats]'
- ! unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'
+ ! [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
) || err_exit "Local: Parent node removed (array element), child still exists"
# remove parent node (array variable) and then check whether the child is gone, too:
(
set -o errexit
unset 'mytree_local1.l1[urw].l2'
- ! unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'
+ ! [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
) || err_exit "Global: Parent node removed (array variable), child still exists"
(
set -o errexit
unset 'mytree_local1.l1[urw].l2'
- ! unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'
+ ! [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
) || err_exit "Local: Parent node removed (array variable), child still exists"
#### test "unset" and compare trees
- unset 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ [[ -v 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]] ; res=$?
+ unset 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'
+ (( res == 0 )) ||
err_exit "Variable 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found."
[[ "${mytree_global1}" != "${mytree_local1}" ]] || err_exit "mytree_global1 and mytree_local1 should differ"
- unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]] ; res=$?
+ unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'
+ (( res == 0 )) ||
err_exit "Variable 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found."
# Compare trees (after "unset")
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_vartree003.sh b/usr/src/lib/libshell/common/tests/sun_solaris_vartree003.sh
index 89bc9e7541..1bab7006c3 100644
--- a/usr/src/lib/libshell/common/tests/sun_solaris_vartree003.sh
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_vartree003.sh
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -31,15 +31,17 @@
# and "unset" handling.
#
+# test setup
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
- (( Errors+=1 ))
+ (( Errors++ ))
}
-
alias err_exit='err_exit $LINENO'
+# the test cannot use "nounset"
+Command=${0##*/}
integer Errors=0
function example_tree
diff --git a/usr/src/lib/libshell/common/tests/tilde.sh b/usr/src/lib/libshell/common/tests/tilde.sh
index 60a2de0aa8..e22626f6df 100644
--- a/usr/src/lib/libshell/common/tests/tilde.sh
+++ b/usr/src/lib/libshell/common/tests/tilde.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -25,6 +25,12 @@ function err_exit
}
alias err_exit='err_exit $LINENO'
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
function home # id
{
typeset IFS=: pwd=/etc/passwd
@@ -36,8 +42,6 @@ function home # id
fi
}
-Command=${0##*/}
-integer Errors=0
OLDPWD=/bin
if [[ ~ != $HOME ]]
then err_exit '~' not $HOME
@@ -69,24 +73,23 @@ do h=$(home $u)
if [[ $h != . ]]
then [[ ~$u -ef $h ]] || err_exit "~$u not $h"
x=~$u
- [[ $x -ef $h ]] || "x=~$u not $h"
+ [[ $x -ef $h ]] || x="~$u not $h"
break
fi
done
-x=~%%
-if [[ $x != '~%%' ]]
-then err_exit 'x='~%%' not '~%%
+x=~g.r.emlin
+if [[ $x != '~g.r.emlin' ]]
+then err_exit "x=~g.r.emlin failed -- expected '~g.r.emlin', got '$x'"
fi
x=~:~
if [[ $x != "$HOME:$HOME" ]]
-then err_exit x=~:~ not $HOME:$HOME
+then err_exit "x=~:~ failed, expected '$HOME:$HOME', got '$x'"
fi
HOME=/
[[ ~ == / ]] || err_exit '~ should be /'
-trap 'rm -rf /tmp/kshtilde$$' EXIT
[[ ~/foo == /foo ]] || err_exit '~/foo should be /foo when ~==/'
-print $'print ~+\n[[ $1 ]] && $0' > /tmp/kshtilde$$
-chmod +x /tmp/kshtilde$$
+print $'print ~+\n[[ $1 ]] && $0' > $tmp/tilde
+chmod +x $tmp/tilde
nl=$'\n'
-[[ $(/tmp/kshtilde$$ foo) == "$PWD$nl$PWD" ]] 2> /dev/null || err_exit 'tilde fails inside a script run by name'
+[[ $($tmp/tilde foo) == "$PWD$nl$PWD" ]] 2> /dev/null || err_exit 'tilde fails inside a script run by name'
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/timetype.sh b/usr/src/lib/libshell/common/tests/timetype.sh
index c2046d5272..94b27843f1 100644
--- a/usr/src/lib/libshell/common/tests/timetype.sh
+++ b/usr/src/lib/libshell/common/tests/timetype.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
diff --git a/usr/src/lib/libshell/common/tests/treemove.sh b/usr/src/lib/libshell/common/tests/treemove.sh
new file mode 100644
index 0000000000..9e83e35e50
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/treemove.sh
@@ -0,0 +1,85 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether "typeset -m" correctly moves local variables
+# into a global variable tree.
+#
+# This was reported as CR #XXXXXXXX ("XXXX"):
+# -- snip --
+#XXXX
+# -- snip --
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+integer Errors=0
+
+## test start
+typeset -C tree1 tree2
+
+# add node to tree which uses "typeset -m" to move a local variable
+# into tree1.subtree["a_node"]
+function f1
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ typeset -C node
+ node.one="hello"
+ node.two="world"
+ # move local note into the array
+false
+ typeset -m tr.subtree["a_node"]=node
+ return 0
+}
+
+# Alternative version which uses "nameref" instead of "typeset -m"
+function f2
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ nameref node=tr.subtree["a_node"]
+ node.one="hello"
+ node.two="world"
+ return 0
+}
+
+f1 tree1
+f2 tree2
+
+[[ "${tree1.subtree["a_node"].one}" == "hello" ]] || err_exit "expected tree1.subtree[\"a_node\"].one == 'hello', got ${tree1.subtree["a_node"].one}"
+[[ "${tree1.subtree["a_node"].two}" == "world" ]] || err_exit "expected tree1.subtree[\"a_node\"].two == 'world', got ${tree1.subtree["a_node"].two}"
+[[ "${tree1}" == "${tree2}" ]] || err_exit "tree1 and tree2 differ:$'\n'"
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/types.sh b/usr/src/lib/libshell/common/tests/types.sh
index 24be9e9863..5904640e07 100644
--- a/usr/src/lib/libshell/common/tests/types.sh
+++ b/usr/src/lib/libshell/common/tests/types.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -27,6 +27,10 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
integer n=2
typeset -T Type_t=(
@@ -109,14 +113,13 @@ x=(a b c)
typeset -m x[1]=x[2]
[[ ${x[1]} == c ]] || err_exit 'move an indexed array element fails'
[[ ${x[2]} ]] && err_exit 'x[2] should be unset after move'
-trap 'rm -f /tmp/kshtype$$' EXIT
-cat > /tmp/kshtype$$ <<- \+++
+cat > $tmp/types <<- \+++
typeset -T Pt_t=(float x=1. y=0.)
Pt_t p=(y=2)
print -r -- ${p.y}
+++
expected=2
-got=$(. /tmp/kshtype$$) 2>/dev/null
+got=$(. $tmp/types) 2>/dev/null
[[ "$got" == "$expected" ]] || err_exit "typedefs in dot script failed -- expected '$expected', got '$got'"
typeset -T X_t=(
typeset x=foo y=bar
@@ -263,6 +266,114 @@ $SHELL > /dev/null <<- '+++++' || err_exit 'passing _ as nameref arg not workin
function f { f1 _ ;}
)
A_t a
- [[ ${ a.f ./t1;} == "$a" ]]
+ [[ ${ a.f ./t1;} == "$a" ]]
+++++
+expected='A_t b.a=(name=one;)'
+[[ $( $SHELL << \+++
+ typeset -T A_t=(
+ typeset name=aha
+ )
+ typeset -T B_t=(
+ typeset arr
+ A_t a
+ f()
+ {
+ _.a=(name=one)
+ typeset -p _.a
+ }
+ )
+ B_t b
+ b.f
++++
+) == "$expected" ]] 2> /dev/null || err_exit '_.a=(name=one) not expanding correctly'
+expected='A_t x=(name=xxx;)'
+[[ $( $SHELL << \+++
+ typeset -T A_t=(
+ typeset name
+ )
+ A_t x=(name="xxx")
+ typeset -p x
++++
+) == "$expected" ]] || err_exit 'empty field in definition does not expand correctly'
+
+typeset -T Foo_t=(
+ integer x=3
+ integer y=4
+ len() { print -r -- $(( sqrt(_.x**2 + _.y**2))) ;}
+)
+Foo_t foo
+[[ ${foo.len} == 5 ]] || err_exit "discipline function len not working"
+
+typeset -T benchmark_t=(
+ integer num_iterations
+)
+function do_benchmarks
+{
+ nameref tst=b
+ integer num_iterations
+ (( num_iterations= int(tst.num_iterations * 1.0) ))
+ printf "%d\n" num_iterations
+}
+benchmark_t b=(num_iterations=5)
+[[ $(do_benchmarks) == 5 ]] || err_exit 'scoping of nameref of type variables in arithmetic expressions not working'
+
+function cat_content
+{
+ cat <<- EOF
+ (
+ foo_t -a foolist=(
+ ( val=3 )
+ ( val=4 )
+ ( val=5 )
+ )
+ )
+ EOF
+ return 0
+}
+typeset -T foo_t=(
+ integer val=-1
+ function print
+ {
+ print -- ${_.val}
+ }
+)
+function do_something
+{
+ nameref li=$1 # "li" may be an index or associative array
+ li[2].print
+}
+cat_content | read -C x
+[[ $(do_something x.foolist) == 5 ]] || err_exit 'subscripts not honored for arrays of type with disciplines'
+
+typeset -T benchcmd_t=(
+ float x=1
+ float y=2
+)
+unset x
+compound x=(
+ float o
+ benchcmd_t -a m
+ integer h
+)
+expected=$'(\n\ttypeset -l -i h=0\n\tbenchcmd_t -a m\n\ttypeset -l -E o=0\n)'
+[[ $x == "$expected" ]] || err_exit 'compound variable with array of types with no elements not working'
+
+expected=$'Std_file_t db.file[/etc/profile]=(action=preserve;typeset -A sum=([8242e663d6f7bb4c5427a0e58e2925f3]=1);)'
+{
+ got=$($SHELL <<- \EOF
+ MAGIC='stdinstall (at&t research) 2009-08-25'
+ typeset -T Std_file_t=(
+ typeset action
+ typeset -A sum
+ )
+ typeset -T Std_t=(
+ typeset magic=$MAGIC
+ Std_file_t -A file
+ )
+ Std_t db=(magic='stdinstall (at&t research) 2009-08-25';Std_file_t -A file=( [/./home/gsf/.env.sh]=(action=preserve;typeset -A sum=([9b67ab407d01a52b3e73e3945b9a3ee0]=1);)[/etc/profile]=(action=preserve;typeset -A sum=([8242e663d6f7bb4c5427a0e58e2925f3]=1);)[/home/gsf/.profile]=(action=preserve;typeset -A sum=([3ce23137335219672bf2865d003a098e]=1);));)
+ typeset -p db.file[/etc/profile]
+ EOF)
+} 2> /dev/null
+[[ $got == "$expected" ]] || err_exit 'types with arrays of types as members fails'
+
exit $Errors
diff --git a/usr/src/lib/libshell/common/tests/variables.sh b/usr/src/lib/libshell/common/tests/variables.sh
index 1808d2fbcf..f174a9a2bf 100644
--- a/usr/src/lib/libshell/common/tests/variables.sh
+++ b/usr/src/lib/libshell/common/tests/variables.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -28,11 +28,14 @@ alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
[[ ${.sh.version} == "$KSH_VERSION" ]] || err_exit '.sh.version != KSH_VERSION'
unset ss
-[[ ${@ss} ]] && err_exit '${@ss} should be empty string when ss is unset'
-[[ ${!ss} == ss ]] || err_exit '${!ss} should be ss when ss is unset'
-[[ ${#ss} == 0 ]] || err_exit '${#ss} should be 0 when ss is unset'
+[[ ${@ss} ]] && err_exit '${@ss} should be empty string when ss is unset'
+[[ ${!ss} == ss ]] || err_exit '${!ss} should be ss when ss is unset'
+[[ ${#ss} == 0 ]] || err_exit '${#ss} should be 0 when ss is unset'
# RANDOM
if (( RANDOM==RANDOM || $RANDOM==$RANDOM ))
then err_exit RANDOM variable not working
@@ -57,17 +60,19 @@ fi
#fi
# PWD
if [[ ! $PWD -ef . ]]
-then err_exit PWD variable not working
+then err_exit PWD variable failed, not equivalent to .
fi
# PPID
-if [[ $($SHELL -c 'print $PPID') != $$ ]]
-then err_exit PPID variable not working
+exp=$$
+got=${ $SHELL -c 'print $PPID'; }
+if [[ ${ $SHELL -c 'print $PPID'; } != $$ ]]
+then err_exit "PPID variable failed -- expected '$exp', got '$got'"
fi
# OLDPWD
old=$PWD
cd /
if [[ $OLDPWD != $old ]]
-then err_exit OLDPWD variable not working
+then err_exit "OLDPWD variable failed -- expected '$old', got '$OLDPWD'"
fi
cd $old || err_exit cd failed
# REPLY
@@ -90,7 +95,7 @@ LINENO=save+10
IFS=:
x=a::b::c
if [[ $x != a::b::c ]]
-then err_exit "Word splitting on constants"
+then err_exit "word splitting on constants"
fi
set -- $x
if [[ $# != 5 ]]
@@ -171,7 +176,7 @@ unset -n foo
foo=junk
function foo.get
{
- .sh.value=stuff
+ .sh.value=stuff
unset -f foo.get
}
if [[ $foo != stuff ]]
@@ -209,22 +214,19 @@ done
kill $!
unset x
CDPATH=/
-x=$(cd tmp)
-if [[ $x != /tmp ]]
+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$$)
+x=$(cd ${tmp%/*}; cd ${tmp##*/})
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"
+x=$(cd ${tmp#/})
+if [[ $x != $tmp ]]
+then err_exit "CDPATH ${tmp#/} does not display new directory"
fi
-cd /
-rm -rf /tmp/ksh$$
TMOUT=100
(TMOUT=20)
if (( TMOUT !=100 ))
@@ -411,15 +413,15 @@ done
unset IFS
if [[ $( (print ${12345:?}) 2>&1) != *12345* ]]
-then err_exit 'Incorrect error message with ${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?}'
+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?}'
+then err_exit 'incorrect error message with ${foobar?}'
fi
{ $SHELL -c '
function foo
@@ -427,14 +429,13 @@ function foo
typeset SECONDS=0
sleep 1.5
print $SECONDS
-
+
}
x=$(foo)
-(( x >1 && x < 2 ))
+(( 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$$ <<-\!
+cat > $tmp/script <<-\!
posixfun()
{
unset x
@@ -451,12 +452,12 @@ cat > /tmp/script$$ <<-\!
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"
+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"
@@ -483,22 +484,22 @@ function dave.unset
unset dave
[[ $(typeset +f) == *dave.* ]] && err_exit 'unset discipline not removed'
-print 'print ${VAR}' > /tmp/script$$
+print 'print ${VAR}' > $tmp/script
unset VAR
-VAR=new /tmp/script$$ > /tmp/out$$
-got=$(</tmp/out$$)
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
[[ $got == new ]] || err_exit "previously unset environment variable not passed to script, expected 'new', got '$got'"
[[ ! $VAR ]] || err_exit "previously unset environment variable set after script, expected '', got '$VAR'"
unset VAR
VAR=old
-VAR=new /tmp/script$$ > /tmp/out$$
-got=$(</tmp/out$$)
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
[[ $got == new ]] || err_exit "environment variable covering local variable not passed to script, expected 'new', got '$got'"
[[ $VAR == old ]] || err_exit "previously set local variable changed after script, expected 'old', got '$VAR'"
unset VAR
export VAR=old
-VAR=new /tmp/script$$ > /tmp/out$$
-got=$(</tmp/out$$)
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
[[ $got == new ]] || err_exit "environment variable covering environment variable not passed to script, expected 'new', got '$got'"
[[ $VAR == old ]] || err_exit "previously set environment variable changed after script, expected 'old', got '$VAR'"
@@ -511,7 +512,7 @@ got=$(</tmp/out$$)
}
dave=foo; dave+=bar
[[ $dave == barfoo ]] || exit 2
-) 2> /dev/null
+) 2> /dev/null
case $? in
0) ;;
1) err_exit 'append discipline not implemented';;
@@ -522,8 +523,8 @@ esac
function .sh.foobar.get
{
.sh.value=world
- }
-} 2> /dev/null || err_exit "Can't add get discipline to .sh.foobar"
+ }
+} 2> /dev/null || err_exit "cannot add get discipline to .sh.foobar"
[[ ${.sh.foobar} == world ]] || err_exit 'get discipline for .sh.foobar not working'
x='a|b'
IFS='|'
@@ -557,12 +558,12 @@ function foo.set
;;
esac
}
-foo[barrier_hit]=no
+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[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'
@@ -576,8 +577,10 @@ function x.set
}
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'
+float seconds
((SECONDS=3*4))
-(( SECONDS < 12 || SECONDS > 12.1 )) && err_exit "SECONDS is $SECONDS and should be close to 12"
+seconds=SECONDS
+(( seconds < 12 || seconds > 12.1 )) && err_exit "SECONDS is $seconds and should be close to 12"
unset a
function a.set
{
@@ -611,15 +614,37 @@ do nameref r=$v
else err_exit "unset $v; : \$$v failed"
fi
done
+
+x=x
for v in LC_ALL LC_CTYPE LC_MESSAGES LC_COLLATE LC_NUMERIC
do nameref r=$v
unset $v
[[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'"
d=$($SHELL -c "$v=$x" 2>&1)
[[ $d ]] || err_exit "$v=$x failed -- expected locale diagnostic"
- ( r=$x; [[ ! $r ]] ) 2>/dev/null || err_exit "$v=$x failed -- expected ''"
- ( r=C; r=$x; [[ $r == C ]] ) 2>/dev/null || err_exit "$v=C; $v=$x failed -- expected 'C'"
+ { g=$( r=$x; print -- $r ); } 2>/dev/null
+ [[ $g == '' ]] || err_exit "$v=$x failed -- expected '', got '$g'"
+ { g=$( r=C; r=$x; print -- $r ); } 2>/dev/null
+ [[ $g == 'C' ]] || err_exit "$v=C; $v=$x failed -- expected 'C', got '$g'"
done
PATH=$path
+cd $tmp
+
+print print -n zzz > zzz
+chmod +x zzz
+exp='aaazzz'
+got=$($SHELL -c 'unset SHLVL; print -n aaa; ./zzz' 2>&1) >/dev/null 2>&1
+[[ $got == "$exp" ]] || err_exit "unset SHLVL causes script failure -- expected '$exp', got '$got'"
+
+mkdir glean
+for cmd in date ok
+do exp="$cmd ok"
+ rm -f $cmd
+ print print $exp > glean/$cmd
+ chmod +x glean/$cmd
+ got=$(CDPATH=:.. $SHELL -c "PATH=:/bin:/usr/bin; date > /dev/null; cd glean && ./$cmd" 2>&1)
+ [[ $got == "$exp" ]] || err_exit "cd with CDPATH after PATH change failed -- expected '$exp', got '$got'"
+done
+
exit $((Errors))
diff --git a/usr/src/lib/libshell/common/tests/vartree1.sh b/usr/src/lib/libshell/common/tests/vartree1.sh
index 88116a24c3..67134086af 100644
--- a/usr/src/lib/libshell/common/tests/vartree1.sh
+++ b/usr/src/lib/libshell/common/tests/vartree1.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -41,7 +41,7 @@ function build_tree
typeset i
typeset dummy
typeset a b c d e f
-
+
nameref dest_tree="$1" # destination tree
nameref srcdata="$2" # source data
typeset tree_mode="$3" # mode to define the type of leads
@@ -53,15 +53,15 @@ function build_tree
for i in "${node.xlfd[@]}" ; do
IFS='-' read dummy a b c d e f <<<"$i"
-
+
if [[ "$a" == "" ]] ; then
a="$dummy"
fi
-
+
[[ "$a" == "" ]] && a='-'
[[ "$b" == "" ]] && b='-'
[[ "$c" == "" ]] && c='-'
-
+
if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
#if ! (unset dest_tree.l1["$a"]) ; then
typeset -A dest_tree.l1["$a"].l2
@@ -75,7 +75,7 @@ function build_tree
if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
fi
-
+
#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries+=( "$index" )
typeset new_index
if [[ "${tree_mode}" == "leaf_name" ]] ; then
@@ -88,12 +88,12 @@ function build_tree
continue
fi
fi
-
+
add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
done
done
-
- return 0
+
+ return 0
}
function add_tree_leaf
@@ -101,7 +101,7 @@ function add_tree_leaf
nameref tree_leafnode="$1"
nameref data_node=srcdata.hashnodes["$2"]
typeset add_mode="$3"
-
+
case "${add_mode}" in
"leaf_name")
tree_leafnode="${data_node.name}"
@@ -121,7 +121,7 @@ function add_tree_leaf
return 1
;;
esac
-
+
# not reached
return 1
}
@@ -151,7 +151,7 @@ typeset mysrcdata_global=(
)
mytree_global=()
-
+
function main
{
# "mysrcdata_local" and "mysrcdata_global" must be identical
@@ -182,32 +182,32 @@ function main
build_tree mytree_global mysrcdata_global leaf_compound || \
err_exit 'build_tree mytree_global mysrcdata_global leaf_compound returned an error'
- (( $(print -r -- "${mytree_global}" | wc -l) > 10 )) || err_exit "Compound tree 'mytree_global' too small."
+ (( $(print -r -- "${mytree_global}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global' too small"
# build tree using local tree variables
mytree_local=()
build_tree mytree_local mysrcdata_local leaf_compound || \
err_exit 'build_tree mytree_local mysrcdata_local leaf_compound returned an error'
- (( $(print -r -- "${mytree_local}" | wc -l) > 10 )) || err_exit "Compound tree 'mytree_local' too small."
-
+ (( $(print -r -- "${mytree_local}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local' too small"
+
# Compare trees
if [[ "${mytree_global}" != "${mytree_local}" ]] ; then
- err_exit "Compound trees 'mytree_local' and 'mytree_global' not identical"
+ err_exit "compound trees 'mytree_local' and 'mytree_global' not identical"
fi
-
+
unset 'mytree_global.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
- err_exit "Variable 'mytree_global.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found."
-
+ err_exit "variable 'mytree_global.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
[[ "${mytree_global}" != "${mytree_local}" ]] || err_exit "mytree_global and mytree_local should differ"
unset 'mytree_local.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
- err_exit "Variable 'mytree_local.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found."
-
+ err_exit "variable 'mytree_local.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
# Compare trees (after "unset")
if [[ "${mytree_global}" != "${mytree_local}" ]] ; then
- err_exit "Compound trees 'mytree_local' and 'mytree_global' not identical after unset"
- fi
+ err_exit "compound trees 'mytree_local' and 'mytree_global' not identical after unset"
+ fi
}
main
diff --git a/usr/src/lib/libshell/common/tests/vartree2.sh b/usr/src/lib/libshell/common/tests/vartree2.sh
index 38512d5a42..9f478ae140 100644
--- a/usr/src/lib/libshell/common/tests/vartree2.sh
+++ b/usr/src/lib/libshell/common/tests/vartree2.sh
@@ -1,7 +1,7 @@
########################################################################
# #
# This software is part of the ast package #
-# Copyright (c) 1982-2008 AT&T Intellectual Property #
+# Copyright (c) 1982-2009 AT&T Intellectual Property #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Intellectual Property #
@@ -34,7 +34,7 @@ function err_exit
alias err_exit='err_exit $LINENO'
# "built_tree1" and "built_tree2" are identical except the way how they test
-# whether a variable exists:
+# whether a variable exists:
# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable
# as non-zero length content
# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell
@@ -46,7 +46,7 @@ function build_tree1
typeset i
typeset dummy
typeset a b c d e f
-
+
nameref dest_tree="$1" # destination tree
nameref srcdata="$2" # source data
typeset tree_mode="$3" # mode to define the type of leads
@@ -58,15 +58,15 @@ function build_tree1
for i in "${node.xlfd[@]}" ; do
IFS='-' read dummy a b c d e f <<<"$i"
-
+
if [[ "$a" == "" ]] ; then
a="$dummy"
fi
-
+
[[ "$a" == "" ]] && a='-'
[[ "$b" == "" ]] && b='-'
[[ "$c" == "" ]] && c='-'
-
+
if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
#if ! (unset dest_tree.l1["$a"]) ; then
typeset -A dest_tree.l1["$a"].l2
@@ -80,7 +80,7 @@ function build_tree1
if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
fi
-
+
typeset new_index
if [[ "${tree_mode}" == "leaf_name" ]] ; then
new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 ))
@@ -92,16 +92,16 @@ function build_tree1
continue
fi
fi
-
+
add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
done
done
-
- return 0
+
+ return 0
}
# "built_tree1" and "built_tree2" are identical except the way how they test
-# whether a variable exists:
+# whether a variable exists:
# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable
# as non-zero length content
# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell
@@ -113,7 +113,7 @@ function build_tree2
typeset i
typeset dummy
typeset a b c d e f
-
+
nameref dest_tree="$1" # destination tree
nameref srcdata="$2" # source data
typeset tree_mode="$3" # mode to define the type of leads
@@ -125,15 +125,15 @@ function build_tree2
for i in "${node.xlfd[@]}" ; do
IFS='-' read dummy a b c d e f <<<"$i"
-
+
if [[ "$a" == "" ]] ; then
a="$dummy"
fi
-
+
[[ "$a" == "" ]] && a='-'
[[ "$b" == "" ]] && b='-'
[[ "$c" == "" ]] && c='-'
-
+
#if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
if ! (unset dest_tree.l1["$a"]) ; then
typeset -A dest_tree.l1["$a"].l2
@@ -147,7 +147,7 @@ function build_tree2
if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
fi
-
+
typeset new_index
if [[ "${tree_mode}" == "leaf_name" ]] ; then
new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 ))
@@ -159,12 +159,12 @@ function build_tree2
continue
fi
fi
-
+
add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
done
done
-
- return 0
+
+ return 0
}
@@ -173,7 +173,7 @@ function add_tree_leaf
nameref tree_leafnode="$1"
nameref data_node=srcdata.hashnodes["$2"]
typeset add_mode="$3"
-
+
case "${add_mode}" in
"leaf_name")
tree_leafnode="${data_node.name}"
@@ -193,7 +193,7 @@ function add_tree_leaf
return 1
;;
esac
-
+
# not reached
return 1
}
@@ -224,7 +224,7 @@ typeset mysrcdata_global=(
mytree_global1=()
mytree_global2=()
-
+
function main
{
# "mysrcdata_local" and "mysrcdata_global" must be identical
@@ -254,11 +254,11 @@ function main
#### Build tree using global tree variables
build_tree1 mytree_global1 mysrcdata_global leaf_compound || \
err_exit 'build_tree1 mytree_global1 mysrcdata_global leaf_compound returned an error'
- (( $(print -r -- "${mytree_global1}" | wc -l) > 10 )) || err_exit "Compound tree 'mytree_global1' too small."
+ (( $(print -r -- "${mytree_global1}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global1' too small"
build_tree2 mytree_global2 mysrcdata_global leaf_compound || \
err_exit 'build_tree2 mytree_global2 mysrcdata_global leaf_compound returned an error'
- (( $(print -r -- "${mytree_global2}" | wc -l) > 10 )) || err_exit "Compound tree 'mytree_global2' too small."
+ (( $(print -r -- "${mytree_global2}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global2' too small"
#### build tree using local tree variables
@@ -267,67 +267,67 @@ function main
build_tree1 mytree_local1 mysrcdata_local leaf_compound || \
err_exit 'build_tree1 mytree_local1 mysrcdata_local leaf_compound returned an error'
- (( $(print -r -- "${mytree_local1}" | wc -l) > 10 )) || err_exit "Compound tree 'mytree_local1' too small."
+ (( $(print -r -- "${mytree_local1}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local1' too small"
build_tree2 mytree_local2 mysrcdata_local leaf_compound || \
err_exit 'build_tree2 mytree_local2 mysrcdata_local leaf_compound returned an error'
- (( $(print -r -- "${mytree_local2}" | wc -l) > 10 )) || err_exit "Compound tree 'mytree_local2' too small."
+ (( $(print -r -- "${mytree_local2}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local2' too small"
+
-
#### Compare treess
if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then
- err_exit "Compound trees 'mytree_global1' and 'mytree_local1' not identical"
+ err_exit "compound trees 'mytree_global1' and 'mytree_local1' not identical"
fi
if [[ "${mytree_global1}" != "${mytree_global2}" ]] ; then
- err_exit "Compound trees 'mytree_global1' and 'mytree_global2' not identical"
+ err_exit "compound trees 'mytree_global1' and 'mytree_global2' not identical"
fi
if [[ "${mytree_local1}" != "${mytree_local2}" ]] ; then
- err_exit "Compound trees 'mytree_local1' and 'mytree_local2' not identical"
+ err_exit "compound trees 'mytree_local1' and 'mytree_local2' not identical"
fi
#### test "unset" in a subshell
( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \
- err_exit "Try 1: Variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found."
+ err_exit "try 1: variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found"
( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \
- err_exit "Try 2: Variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found."
+ err_exit "try 2: variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found"
# remove parent node (array element) and then check whether the child is gone, too:
(
unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]'
- unset 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'
- ) && err_exit "Global: Parent node removed (array element), child still exists"
+ [[ -v 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'} ]]
+ ) && err_exit "global: parent node removed (array element), child still exists"
(
unset 'mytree_local1.l1[urw].l2[itc zapfdingbats]'
- unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'
- ) && err_exit "Local: Parent node removed (array element), child still exists"
-
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "local: parent node removed (array element), child still exists"
+
# remove parent node (array variable) and then check whether the child is gone, too:
(
unset 'mytree_local1.l1[urw].l2'
- unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'
- ) && err_exit "Global: Parent node removed (array variable), child still exists"
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "global: parent node removed (array variable), child still exists"
(
unset 'mytree_local1.l1[urw].l2'
- unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'
- ) && err_exit "Local: Parent node removed (array variable), child still exists"
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "local: parent node removed (array variable), child still exists"
#### test "unset" and compare trees
unset 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
- err_exit "Variable 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found."
-
+ err_exit "variable 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
[[ "${mytree_global1}" != "${mytree_local1}" ]] || err_exit "mytree_global1 and mytree_local1 should differ"
unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
- err_exit "Variable 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found."
-
+ err_exit "variable 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
# Compare trees (after "unset")
if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then
- err_exit "Compound trees 'mytree_local1' and 'mytree_global1' not identical after unset"
- fi
+ err_exit "compound trees 'mytree_local1' and 'mytree_global1' not identical after unset"
+ fi
}
main