summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common/tests
diff options
context:
space:
mode:
authorRoland Mainz <roland.mainz@nrubsig.org>2009-10-28 10:36:39 -0700
committerRoland Mainz <roland.mainz@nrubsig.org>2009-10-28 10:36:39 -0700
commit34f9b3eef6fdadbda0a846aa4d68691ac40eace5 (patch)
tree0b0fdfb35f8eb9324728de5a99e50e939aca650f /usr/src/lib/libshell/common/tests
parent14969419acb89bb74e6c95fa472119b710224440 (diff)
downloadillumos-gate-34f9b3eef6fdadbda0a846aa4d68691ac40eace5.tar.gz
Portions contributed by Olga Kryzhanovska <olga.kryzhanovska@gmail.com>
PSARC/2009/063 ksh93 update 2 PSARC/2009/248 ksh93 update to 2009-03-10 PSARC/2009/249 more ksh93 command conversions 6888396 libast sources should not include localedef.h 6605478 ksh93 profile shell option does not work 6631006 ksh93 hangs in situations that ksh handles okay 6661487 logname reports nothing after running the script command 6705126 first call to read doesn't honor new setting of HISTFILE 6764665 *libpp* Array overrun in libpp 6765756 *libast* Array overruns in libast 6769332 Recursive function+command substitutions terminate shell after 257 iterations 6777491 *ksh93* lacks arithmetric function iszero() 6778077 *ksh93* does not understand "THAW" as a signal for use with trap 6789247 [ku1] libast/ksh93 1-digit hexfloat base conversion rounds incorrectly 6791838 *ksh93* unset of a variable which is not set should return 0 6793714 RFE: Update /usr/bin/comm to AT&T AST "comm" 6793719 RFE: Update /usr/bin/cut to AT&T AST "cut" 6793721 RFE: Update /usr/bin/paste to AT&T AST "paste" 6793722 RFE: Update /usr/bin/cmp to AT&T AST "cmp" 6793726 RFE: Update /usr/bin/uniq to AT&T AST "uniq" 6793735 RFE: Update /usr/bin/wc to AT&T AST "wc" 6793744 RFE: Add /usr/share/doc/ksh/ for ksh93 documentation 6793747 RFE: Provide "print" builtin as /usr/bin/print for external applications 6793763 RFE: Update /usr/bin/ksh93 to ast-ksh.2009-05-05 6794952 RFE: Enable "globstar" mode in /etc/ksh.kshrc (= interactive ksh93 shells) 6805792 [ku1] Moving local compound var into array does not work 6805794 [ku1] printf returns "invalid character constant" for $ printf "%d\n" "'<euro>" 6805795 [ku1] ksh93 does not differ between -0 and +0 6805797 [ku1]Can't append to nodes of an array of compound vars if addressing them via nameref 6805799 Indexed compound variable arrays do not work... 6805800 [ku1] Declaring associative compound array does not work 6805813 RFE: Update /usr/bin/join to AT&T AST "join". 6805819 RFE: Update /usr/bin/tee to AT&T AST "tee". 6809663 shlint missing ending newline on errors 6811916 ksh93 repeatedly segfaults when "tee" builtin is interrupted via <ctrl-c> in interactive mode 6821113 SUNWosdem package issues 6828644 RFE: Update /usr/bin/logname to AT&T AST "logname". 6828692 RFE: Update /usr/bin/cksum to AT&T AST "cksum". 6834184 ksh93 gets SIGSEGV if HISTFILE is changed in place. 6834207 ksh93 gets SIGSEGV on interactive function definition with HISTSIZE unset 6835835 ksh93 "cat" builtin does not handle "-n" correctly 6841442 Need exception list for OS/Net trees managed via Subversion 6848486 "echo ${test}" with test undefined crashes the shell 6850672 ksh93 (VISUAL=vi) crashes with memory fault while scrolling through history 6855875 typeset -X x ; print $x # does not print sufficient digits to restore value 6857344 /usr/bin/hash core dump with invalid arguments 6866676 Need test suite module to test the kernel support for compiled shell scripts 6881017 Subshell doesn't exit, holds pipe open preventing callers from exiting 6884409 fts functions in libast library can result in segv with deep dir trees (similar to CERT VU#590371)
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