14887Schin########################################################################
24887Schin#                                                                      #
34887Schin#               This software is part of the ast package               #
4*8462SApril.Chin@Sun.COM#          Copyright (c) 1982-2008 AT&T Intellectual Property          #
54887Schin#                      and is licensed under the                       #
64887Schin#                  Common Public License, Version 1.0                  #
7*8462SApril.Chin@Sun.COM#                    by AT&T Intellectual Property                     #
84887Schin#                                                                      #
94887Schin#                A copy of the License is available at                 #
104887Schin#            http://www.opensource.org/licenses/cpl1.0.txt             #
114887Schin#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
124887Schin#                                                                      #
134887Schin#              Information and Software Systems Research               #
144887Schin#                            AT&T Research                             #
154887Schin#                           Florham Park NJ                            #
164887Schin#                                                                      #
174887Schin#                  David Korn <dgk@research.att.com>                   #
184887Schin#                                                                      #
194887Schin########################################################################
204887Schinfunction err_exit
214887Schin{
224887Schin	print -u2 -n "\t"
234887Schin	print -u2 -r ${Command}[$1]: "${@:2}"
244887Schin	let Errors+=1
254887Schin}
264887Schinalias err_exit='err_exit $LINENO'
274887Schin
284887SchinCommand=${0##*/}
294887Schininteger Errors=0
30*8462SApril.Chin@Sun.COM
31*8462SApril.Chin@Sun.COMunset HISTFILE
32*8462SApril.Chin@Sun.COM
334887Schinfunction fun
344887Schin{
354887Schin	while  command exec 3>&1
364887Schin	do	break
374887Schin	done 2>   /dev/null
384887Schin	print -u3 good
394887Schin}
404887Schinprint 'read -r a;print -r -u$1 -- "$a"' >  /tmp/mycat$$
414887Schinchmod 755 /tmp/mycat$$
424887Schinfor ((i=3; i < 10; i++))
434887Schindo
444887Schin	eval "a=\$(print foo | /tmp/mycat$$" $i $i'>&1 > /dev/null |cat)' 2> /dev/null
454887Schin	[[ $a == foo ]] || err_exit "bad file descriptor $i in comsub script"
464887Schindone
474887Schinrm -f /tmp/mycat$$
484887Schinexec 3> /dev/null
494887Schin[[ $(fun) == good ]] || err_exit 'file 3 closed before subshell completes'
504887Schinexec 3>&-
514887Schinmkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed"
524887Schintrap 'rm -rf /tmp/ksh$$' EXIT
534887Schincd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed"
544887Schinprint foo > file1
554887Schinprint bar >> file1
564887Schinif	[[ $(<file1) != $'foo\nbar' ]]
574887Schinthen	err_exit 'append (>>) not working'
584887Schinfi
594887Schinset -o noclobber
604887Schinexec 3<> file1
614887Schinread -u3 line
624887Schinif	[[ $line != foo ]]
634887Schinthen	err_exit '<> not working right with read'
644887Schinfi
654887Schinif	( 4> file1 ) 2> /dev/null
664887Schinthen	err_exit 'noclobber not causing exclusive open'
674887Schinfi
684887Schinset +o noclobber
694887Schinif	command exec 4< /dev/fd/3
704887Schinthen	read -u4 line
714887Schin	if	[[ $line != bar ]]
724887Schin	then	'4< /dev/fd/3 not working correctly'
734887Schin	fi
744887Schinfi
754887Schincat > close0 <<\!
764887Schinexec 0<&-
774887Schinecho $(./close1)
784887Schin!
794887Schinprint "echo abc" > close1
804887Schinchmod +x close0 close1
814887Schinx=$(./close0)
824887Schinif	[[ $x != "abc" ]]
834887Schinthen	err_exit "picked up file descriptor zero for opening script file"
844887Schinfi
854887Schincat > close0 <<\!
864887Schin	for ((i=0; i < 1100; i++))
874887Schin	do	exec 4< /dev/null
884887Schin		read -u4
894887Schin	done
904887Schin	exit 0
914887Schin!
924887Schin./close0 2> /dev/null || err_exit "multiple exec 4< /dev/null can fail"
934887Schin$SHELL -c '
944887Schin	trap "rm -f in$$ out$$" EXIT
954887Schin	for ((i = 0; i < 1000; i++))
964887Schin	do	print -r -- "This is a test"
974887Schin	done > in$$
984887Schin	> out$$
994887Schin	exec 1<> out$$
1004887Schin	builtin cat
1014887Schin	print -r -- "$(cat in$$)"
1024887Schin	cmp -s in$$ out$$'  2> /dev/null
1034887Schin[[ $? == 0 ]] || err_exit 'builtin cat truncates files'
1044887Schincat >| script <<-\!
1054887Schinprint hello
1064887Schin( exec 3<&- 4<&-)
1074887Schinexec 3<&- 4<&-
1084887Schinprint world
1094887Schin!
1104887Schinchmod +x script
1114887Schin[[ $( $SHELL ./script) == $'hello\nworld' ]] || err_exit 'closing 3 & 4 causes script to fail'
1124887Schincd ~- || err_exit "cd back failed"
1134887Schin( exec  > '' ) 2> /dev/null  && err_exit '> "" does not fail'
1144887Schinunset x
1154887Schin( exec > ${x} ) 2> /dev/null && err_exit '> $x, where x null does not fail'
1164887Schinexec <<!
1174887Schinfoo
1184887Schinbar
1194887Schin!
1204887Schin( exec 0< /dev/null)
1214887Schinread line
1224887Schinif	[[ $line != foo ]]
1234887Schinthen	err_exit 'file descriptor not restored after exec in subshell'
1244887Schinfi
1254887Schinexec 3>&- 4>&-; cd /; rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed"
1264887Schin[[ $( {
1274887Schin	read -r line;print -r -- "$line"
1284887Schin	(
1294887Schin	        read -r line;print -r -- "$line"
1304887Schin	) & wait
1314887Schin	while	read -r line
1324887Schin        do	print -r -- "$line"
1334887Schin	done
1344887Schin } << !
1354887Schinline 1
1364887Schinline 2
1374887Schinline 3
1384887Schin!) == $'line 1\nline 2\nline 3' ]] || err_exit 'read error with subshells'
1394887Schin# 2004-05-11 bug fix
1404887Schincat > /tmp/io$$.1 <<- \++EOF++
1414887Schin	script=/tmp/io$$.2
1424887Schin	trap 'rm -f $script' EXIT
1434887Schin	exec 9> $script
1444887Schin	for ((i=3; i<9; i++))
1454887Schin	do	eval "while read -u$i; do : ;done $i</dev/null"
1464887Schin		print -u9 "exec $i< /dev/null"
1474887Schin	done
1484887Schin	for ((i=0; i < 60; i++))
1494887Schin	do	print -u9 -f "%.80c\n"  ' '
1504887Schin	done
1514887Schin	print -u9 'print ok'
1524887Schin	exec 9<&-
1534887Schin	chmod +x $script
1544887Schin	$script
1554887Schin++EOF++
1564887Schinchmod +x /tmp/io$$.1
1574887Schin[[ $($SHELL  /tmp/io$$.1) == ok ]]  || err_exit "parent i/o causes child script to fail"
1584887Schinrm -rf /tmp/io$$.[12]
1594887Schin# 2004-11-25 ancient /dev/fd/NN redirection bug fix
1604887Schinx=$(
1614887Schin	{
1624887Schin		print -n 1
1634887Schin		print -n 2 > /dev/fd/2
1644887Schin		print -n 3
1654887Schin		print -n 4 > /dev/fd/2
1664887Schin	}  2>&1
1674887Schin)
1684887Schin[[ $x == "1234" ]] || err_exit "/dev/fd/NN redirection fails to dup"
1694887Schin# 2004-12-20 redirction loss bug fix
1704887Schincat > /tmp/io$$.1 <<- \++EOF++
1714887Schin	function a
1724887Schin	{
1734887Schin		trap 'print ok' EXIT
1744887Schin		: > /dev/null
1754887Schin	}
1764887Schin	a
1774887Schin++EOF++
1784887Schinchmod +x /tmp/io$$.1
1794887Schin[[ $(/tmp/io$$.1) == ok ]] || err_exit "trap on EXIT loses last command redirection"
1804887Schinprint > /dev/null {n}> /tmp/io$$.1
1814887Schin[[ ! -s /tmp/io$$.1 ]] && newio=1
1824887Schinrm -rf /tmp/io$$.1
1834887Schinif	[[ $newio && $(print hello | while read -u$n; do print $REPLY; done {n}<&0) != hello ]]
1844887Schinthen	err_exit "{n}<&0 not working with for loop"
1854887Schinfi
1864887Schin[[ $({ read -r;read -u3 3<&0; print -- "$REPLY" ;} <<!
1874887Schinhello
1884887Schinworld
1894887Schin!) == world ]] || err_exit 'I/O not synchronized with <&'
1904887Schintrap 'rm -f /tmp/seek$$; exit $((Errors+1))' EXIT
1914887Schinx="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNSPQRSTUVWXYZ1234567890"
1924887Schinfor ((i=0; i < 62; i++))
1934887Schindo	printf "%.39c\n"  ${x:i:1}
1944887Schindone >  /tmp/seek$$
1954887Schinif	command exec 3<> /tmp/seek$$
1964887Schinthen	(( $(3<#) == 0 )) || err_exit "not at position 0"
1974887Schin	(( $(3<# ((EOF))) == 40*62 )) || err_exit "not at end-of-file"
1984887Schin	command exec 3<# ((40*8)) || err_exit "absolute seek fails"
1994887Schin	read -u3
2004887Schin	[[ $REPLY == +(i) ]] || err_exit "expecting iiii..."
2014887Schin	[[ $(3<#) == $(3<# ((CUR)) ) ]] || err_exit '$(3<#)!=$(3<#((CUR)))'
2024887Schin	command exec 3<# ((CUR+80))
2034887Schin	read -u3
2044887Schin	[[ $REPLY == {39}(l) ]] || err_exit "expecting lll..."
2054887Schin	command exec 3<# ((EOF-80))
2064887Schin	read -u3
2074887Schin	[[ $REPLY == +(9) ]] || err_exit "expecting 999...; got $REPLY"
2084887Schin	command exec 3># ((80))
2094887Schin	print -u3 -f "%.39c\n"  @
2104887Schin	command exec 3># ((80))
2114887Schin	read -u3
2124887Schin	[[ $REPLY == +(@) ]] || err_exit "expecting @@@..."
2134887Schin	read -u3
2144887Schin	[[ $REPLY == +(d) ]] || err_exit "expecting ddd..."
2154887Schin	command exec 3># ((EOF))
2164887Schin	print -u3 -f "%.39c\n"  ^
2174887Schin	(( $(3<# ((CUR-0))) == 40*63 )) || err_exit "not at extended end-of-file"
2184887Schin	command exec 3<# ((40*62))
2194887Schin	read -u3
2204887Schin	[[ $REPLY == +(^) ]] || err_exit "expecting ddd..."
2214887Schin	command exec 3<# ((0))
2224887Schin	command exec 3<# *jjjj*
2234887Schin	read -u3
2244887Schin	[[  $REPLY == {39}(j) ]] || err_exit "<# pattern failed"
2254887Schin	[[ $(command exec 3<## *llll*) = {39}(k) ]] || err_exit "<## pattern not saving standard output"
2264887Schin	read -u3
2274887Schin	[[  $REPLY == {39}(l) ]] || err_exit "<## pattern failed to position"
2284887Schin	command exec 3<# *abc*
2294887Schin	read -u3 && err_exit "not found pattern not positioning at eof"
2304887Schin	cat /tmp/seek$$ | read -r <# *WWW*
2314887Schin	[[ $REPLY == *WWWWW* ]] || err_exit '<# not working for pipes'
232*8462SApril.Chin@Sun.COM	{ < /tmp/seek$$ <# ((2358336120)) ;} 2> /dev/null || err_exit 'long seek not working'
2334887Schinelse	err_exit "/tmp/seek$$: cannot open for reading"
2344887Schinfi
235*8462SApril.Chin@Sun.COMcommand exec 3<&- || 'cannot close 3'
236*8462SApril.Chin@Sun.COMfor ((i=0; i < 62; i++))
237*8462SApril.Chin@Sun.COMdo	printf "%.39c\n"  ${x:i:1}
238*8462SApril.Chin@Sun.COMdone >  /tmp/seek$$
239*8462SApril.Chin@Sun.COMif	command exec {n}<> /tmp/seek$$
240*8462SApril.Chin@Sun.COMthen	{ command exec {n}<#((EOF)) ;} 2> /dev/null || err_exit '{n}<# not working'
241*8462SApril.Chin@Sun.COM	if	$SHELL -c '{n}</dev/null' 2> /dev/null
242*8462SApril.Chin@Sun.COM	then	(( $({n}<#) ==  40*62))  || err_exit '$({n}<#) not working'
243*8462SApril.Chin@Sun.COM	else	err_exit 'not able to parse {n}</dev/null'
244*8462SApril.Chin@Sun.COM	fi
245*8462SApril.Chin@Sun.COMfi
2464887Schintrap "" EXIT
2474887Schinrm -f  /tmp/seek$$
2484887Schin$SHELL -ic '
2494887Schin{
2504887Schin    print -u2  || exit 2
2514887Schin    print -u3  || exit 3
2524887Schin    print -u4  || exit 4
2534887Schin    print -u5  || exit 5
2544887Schin    print -u6  || exit 6
2554887Schin    print -u7  || exit 7
2564887Schin    print -u8  || exit 8
2574887Schin    print -u9  || exit 9
2584887Schin}  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
2594887Schinexitval=$?
2604887Schin(( exitval ))  && err_exit  "print to unit $exitval failed"
2614887Schintrap 'rm -rf /tmp/io.sh$$*' EXIT
2624887Schin$SHELL -c "{ > /tmp/io.sh$$.1 ; date;} >&- 2> /dev/null" > /tmp/io.sh$$.2
2634887Schin[[ -s /tmp/io.sh$$.1 || -s /tmp/io.sh$$.2 ]] && err_exit 'commands with standard output closed produce output'
2644887Schin$SHELL -c "$SHELL -c ': 3>&1' 1>&- 2>/dev/null" && err_exit 'closed standard output not passed to subshell'
265*8462SApril.Chin@Sun.COM[[ $(cat  <<- \EOF | $SHELL
266*8462SApril.Chin@Sun.COM	do_it_all()
267*8462SApril.Chin@Sun.COM	{
268*8462SApril.Chin@Sun.COM	 	dd 2>/dev/null  # not a ksh93 buildin
269*8462SApril.Chin@Sun.COM	 	return $?
270*8462SApril.Chin@Sun.COM	}
271*8462SApril.Chin@Sun.COM	do_it_all ; exit $?
272*8462SApril.Chin@Sun.COM	hello world
273*8462SApril.Chin@Sun.COMEOF) == 'hello world' ]] || err_exit 'invalid readahead on stdin'
274*8462SApril.Chin@Sun.COM$SHELL -c 'exec 3>; /dev/null'  2> /dev/null && err_exit '>; with exec should be an error'
275*8462SApril.Chin@Sun.COM$SHELL -c ': 3>; /dev/null'  2> /dev/null || err_exit '>; not working with at all'
276*8462SApril.Chin@Sun.COMprint hello > /tmp/io.sh$$.1
277*8462SApril.Chin@Sun.COMif	! $SHELL -c "false >; /tmp/io.sh$$.1"  2> /dev/null
278*8462SApril.Chin@Sun.COMthen	[[ $(</tmp/io.sh$$.1) == hello ]] || err_exit '>; not preserving file on failure'
279*8462SApril.Chin@Sun.COMfi
280*8462SApril.Chin@Sun.COMif	! $SHELL -c "sed -e 's/hello/hello world/' /tmp/io.sh$$.1" >; /tmp/io.sh$$.1  2> /dev/null
281*8462SApril.Chin@Sun.COMthen	[[ $(</tmp/io.sh$$.1) == 'hello world' ]] || err_exit '>; not updating file on success'
282*8462SApril.Chin@Sun.COMfi
283*8462SApril.Chin@Sun.COM
284*8462SApril.Chin@Sun.COMunset y
285*8462SApril.Chin@Sun.COMread -n1 y <<!
286*8462SApril.Chin@Sun.COMabc
287*8462SApril.Chin@Sun.COM!
288*8462SApril.Chin@Sun.COMif      [[ $y != a ]]
289*8462SApril.Chin@Sun.COMthen    err_exit  'read -n1 not working'
290*8462SApril.Chin@Sun.COMfi
291*8462SApril.Chin@Sun.COMunset a
292*8462SApril.Chin@Sun.COM{ read -N3 a; read -N1 b;}  <<!
293*8462SApril.Chin@Sun.COMabcdefg
294*8462SApril.Chin@Sun.COM!
295*8462SApril.Chin@Sun.COM[[ $a == abc ]] || err_exit 'read -N3 here-document not working'
296*8462SApril.Chin@Sun.COM[[ $b == d ]] || err_exit 'read -N1 here-document not working'
297*8462SApril.Chin@Sun.COMread -n3 a <<!
298*8462SApril.Chin@Sun.COMabcdefg
299*8462SApril.Chin@Sun.COM!
300*8462SApril.Chin@Sun.COM[[ $a == abc ]] || err_exit 'read -n3 here-document not working'
301*8462SApril.Chin@Sun.COM(print -n a;sleep 1; print -n bcde) | { read -N3 a; read -N1 b;}
302*8462SApril.Chin@Sun.COM[[ $a == abc ]] || err_exit 'read -N3 from pipe not working'
303*8462SApril.Chin@Sun.COM[[ $b == d ]] || err_exit 'read -N1 from pipe not working'
304*8462SApril.Chin@Sun.COM(print -n a;sleep 1; print -n bcde) |read -n3 a
305*8462SApril.Chin@Sun.COM[[ $a == a ]] || err_exit 'read -n3 from pipe not working'
306*8462SApril.Chin@Sun.COMrm -f /tmp/fifo$$
307*8462SApril.Chin@Sun.COMif	mkfifo /tmp/fifo$$ 2> /dev/null
308*8462SApril.Chin@Sun.COMthen	(print -n a; sleep 1;print -n bcde)  > /tmp/fifo$$ &
309*8462SApril.Chin@Sun.COM	{
310*8462SApril.Chin@Sun.COM	read -u5 -n3  -t2 a  || err_exit 'read -n3 from fifo timedout'
311*8462SApril.Chin@Sun.COM	read -u5 -n1 -t2 b || err_exit 'read -n1 from fifo timedout'
312*8462SApril.Chin@Sun.COM	} 5< /tmp/fifo$$
313*8462SApril.Chin@Sun.COM	[[ $a == a ]] || err_exit 'read -n3 from fifo not working'
314*8462SApril.Chin@Sun.COM	rm -f /tmp/fifo$$
315*8462SApril.Chin@Sun.COM	mkfifo /tmp/fifo$$ 2> /dev/null
316*8462SApril.Chin@Sun.COM	(print -n a; sleep 1;print -n bcde)  > /tmp/fifo$$ &
317*8462SApril.Chin@Sun.COM	{
318*8462SApril.Chin@Sun.COM	read -u5 -N3 -t2 a || err_exit 'read -N3 from fifo timed out'
319*8462SApril.Chin@Sun.COM	read -u5 -N1 -t2 b || err_exit 'read -N1 from fifo timedout'
320*8462SApril.Chin@Sun.COM	} 5< /tmp/fifo$$
321*8462SApril.Chin@Sun.COM	[[ $a == abc ]] || err_exit 'read -N3 from fifo not working'
322*8462SApril.Chin@Sun.COM	[[ $b == d ]] || err_exit 'read -N1 from fifo not working'
323*8462SApril.Chin@Sun.COMfi
324*8462SApril.Chin@Sun.COMrm -f /tmp/fifo$$
325*8462SApril.Chin@Sun.COM
326*8462SApril.Chin@Sun.COMif	$SHELL -c "export LC_ALL=en_US.UTF-8; c=$'\342\202\254'; [[ \${#c} == 1 ]]" 2>/dev/null
327*8462SApril.Chin@Sun.COMthen	lc_utf8=en_US.UTF-8
328*8462SApril.Chin@Sun.COMelse	lc_utf8=''
329*8462SApril.Chin@Sun.COMfi
330*8462SApril.Chin@Sun.COM
331*8462SApril.Chin@Sun.COMtypeset -a e o=(-n2 -N2)
332*8462SApril.Chin@Sun.COMinteger i
333*8462SApril.Chin@Sun.COMset -- \
334*8462SApril.Chin@Sun.COM	'a'	'bcd'	'a bcd'	'ab cd' \
335*8462SApril.Chin@Sun.COM	'ab'	'cd'	'ab cd'	'ab cd' \
336*8462SApril.Chin@Sun.COM	'abc'	'd'	'ab cd'	'ab cd' \
337*8462SApril.Chin@Sun.COM	'abcd'	''	'ab cd'	'ab cd'
338*8462SApril.Chin@Sun.COMwhile	(( $# >= 3 ))
339*8462SApril.Chin@Sun.COMdo	a=$1
340*8462SApril.Chin@Sun.COM	b=$2
341*8462SApril.Chin@Sun.COM	e[0]=$3
342*8462SApril.Chin@Sun.COM	e[1]=$4
343*8462SApril.Chin@Sun.COM	shift 4
344*8462SApril.Chin@Sun.COM	for ((i = 0; i < 2; i++))
345*8462SApril.Chin@Sun.COM	do	for lc_all in C $lc_utf8
346*8462SApril.Chin@Sun.COM		do	g=$(LC_ALL=$lc_all $SHELL -c "{ print -n '$a'; sleep 0.2; print -n '$b'; sleep 0.2; } | { read ${o[i]} a; print -n \$a; read a; print -n \ \$a; }")
347*8462SApril.Chin@Sun.COM			[[ $g == "${e[i]}" ]] || err_exit "LC_ALL=$lc_all read ${o[i]} from pipe '$a $b' failed -- expected '${e[i]}', got '$g'"
348*8462SApril.Chin@Sun.COM		done
349*8462SApril.Chin@Sun.COM	done
350*8462SApril.Chin@Sun.COMdone
351*8462SApril.Chin@Sun.COM
352*8462SApril.Chin@Sun.COMif	[[ $lc_utf8 ]]
353*8462SApril.Chin@Sun.COMthen	export LC_ALL=en_US.UTF-8
354*8462SApril.Chin@Sun.COM	typeset -a c=( '' 'A' $'\303\274' $'\342\202\254' )
355*8462SApril.Chin@Sun.COM	integer i w
356*8462SApril.Chin@Sun.COM	typeset o
357*8462SApril.Chin@Sun.COM	if	(( ${#c[2]} == 1 && ${#c[3]} == 1 ))
358*8462SApril.Chin@Sun.COM	then	for i in 1 2 3
359*8462SApril.Chin@Sun.COM		do	for o in n N
360*8462SApril.Chin@Sun.COM			do	for w in 1 2 3
361*8462SApril.Chin@Sun.COM				do	print -nr "${c[w]}" | read -${o}${i} g
362*8462SApril.Chin@Sun.COM					if	[[ $o == N ]] && (( i > 1 ))
363*8462SApril.Chin@Sun.COM					then	e=''
364*8462SApril.Chin@Sun.COM					else	e=${c[w]}
365*8462SApril.Chin@Sun.COM					fi
366*8462SApril.Chin@Sun.COM					[[ $g == "$e" ]] || err_exit "read -${o}${i} failed for '${c[w]}' -- expected '$e', got '$g'"
367*8462SApril.Chin@Sun.COM				done
368*8462SApril.Chin@Sun.COM			done
369*8462SApril.Chin@Sun.COM		done
370*8462SApril.Chin@Sun.COM	fi
371*8462SApril.Chin@Sun.COMfi
372*8462SApril.Chin@Sun.COM
3734887Schinexit $((Errors))
374