1*4887Schin########################################################################
2*4887Schin#                                                                      #
3*4887Schin#               This software is part of the ast package               #
4*4887Schin#           Copyright (c) 1982-2007 AT&T Knowledge Ventures            #
5*4887Schin#                      and is licensed under the                       #
6*4887Schin#                  Common Public License, Version 1.0                  #
7*4887Schin#                      by AT&T Knowledge Ventures                      #
8*4887Schin#                                                                      #
9*4887Schin#                A copy of the License is available at                 #
10*4887Schin#            http://www.opensource.org/licenses/cpl1.0.txt             #
11*4887Schin#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
12*4887Schin#                                                                      #
13*4887Schin#              Information and Software Systems Research               #
14*4887Schin#                            AT&T Research                             #
15*4887Schin#                           Florham Park NJ                            #
16*4887Schin#                                                                      #
17*4887Schin#                  David Korn <dgk@research.att.com>                   #
18*4887Schin#                                                                      #
19*4887Schin########################################################################
20*4887Schinfunction err_exit
21*4887Schin{
22*4887Schin	print -u2 -n "\t"
23*4887Schin	print -u2 -r ${Command}[$1]: "${@:2}"
24*4887Schin	let Errors+=1
25*4887Schin}
26*4887Schinalias err_exit='err_exit $LINENO'
27*4887Schin
28*4887SchinCommand=${0##*/}
29*4887Schininteger Errors=0
30*4887Schin# cut here
31*4887Schinfunction fun
32*4887Schin{
33*4887Schin	while  command exec 3>&1
34*4887Schin	do	break
35*4887Schin	done 2>   /dev/null
36*4887Schin	print -u3 good
37*4887Schin}
38*4887Schinprint 'read -r a;print -r -u$1 -- "$a"' >  /tmp/mycat$$
39*4887Schinchmod 755 /tmp/mycat$$
40*4887Schinfor ((i=3; i < 10; i++))
41*4887Schindo
42*4887Schin	eval "a=\$(print foo | /tmp/mycat$$" $i $i'>&1 > /dev/null |cat)' 2> /dev/null
43*4887Schin	[[ $a == foo ]] || err_exit "bad file descriptor $i in comsub script"
44*4887Schindone
45*4887Schinrm -f /tmp/mycat$$
46*4887Schinexec 3> /dev/null
47*4887Schin[[ $(fun) == good ]] || err_exit 'file 3 closed before subshell completes'
48*4887Schinexec 3>&-
49*4887Schinmkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed"
50*4887Schintrap 'rm -rf /tmp/ksh$$' EXIT
51*4887Schincd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed"
52*4887Schinprint foo > file1
53*4887Schinprint bar >> file1
54*4887Schinif	[[ $(<file1) != $'foo\nbar' ]]
55*4887Schinthen	err_exit 'append (>>) not working'
56*4887Schinfi
57*4887Schinset -o noclobber
58*4887Schinexec 3<> file1
59*4887Schinread -u3 line
60*4887Schinif	[[ $line != foo ]]
61*4887Schinthen	err_exit '<> not working right with read'
62*4887Schinfi
63*4887Schinif	( 4> file1 ) 2> /dev/null
64*4887Schinthen	err_exit 'noclobber not causing exclusive open'
65*4887Schinfi
66*4887Schinset +o noclobber
67*4887Schinif	command exec 4< /dev/fd/3
68*4887Schinthen	read -u4 line
69*4887Schin	if	[[ $line != bar ]]
70*4887Schin	then	'4< /dev/fd/3 not working correctly'
71*4887Schin	fi
72*4887Schinfi
73*4887Schincat > close0 <<\!
74*4887Schinexec 0<&-
75*4887Schinecho $(./close1)
76*4887Schin!
77*4887Schinprint "echo abc" > close1
78*4887Schinchmod +x close0 close1
79*4887Schinx=$(./close0)
80*4887Schinif	[[ $x != "abc" ]]
81*4887Schinthen	err_exit "picked up file descriptor zero for opening script file"
82*4887Schinfi
83*4887Schincat > close0 <<\!
84*4887Schin	for ((i=0; i < 1100; i++))
85*4887Schin	do	exec 4< /dev/null
86*4887Schin		read -u4
87*4887Schin	done
88*4887Schin	exit 0
89*4887Schin!
90*4887Schin./close0 2> /dev/null || err_exit "multiple exec 4< /dev/null can fail"
91*4887Schin$SHELL -c '
92*4887Schin	trap "rm -f in$$ out$$" EXIT
93*4887Schin	for ((i = 0; i < 1000; i++))
94*4887Schin	do	print -r -- "This is a test"
95*4887Schin	done > in$$
96*4887Schin	> out$$
97*4887Schin	exec 1<> out$$
98*4887Schin	builtin cat
99*4887Schin	print -r -- "$(cat in$$)"
100*4887Schin	cmp -s in$$ out$$'  2> /dev/null
101*4887Schin[[ $? == 0 ]] || err_exit 'builtin cat truncates files'
102*4887Schincat >| script <<-\!
103*4887Schinprint hello
104*4887Schin( exec 3<&- 4<&-)
105*4887Schinexec 3<&- 4<&-
106*4887Schinprint world
107*4887Schin!
108*4887Schinchmod +x script
109*4887Schin[[ $( $SHELL ./script) == $'hello\nworld' ]] || err_exit 'closing 3 & 4 causes script to fail'
110*4887Schincd ~- || err_exit "cd back failed"
111*4887Schin( exec  > '' ) 2> /dev/null  && err_exit '> "" does not fail'
112*4887Schinunset x
113*4887Schin( exec > ${x} ) 2> /dev/null && err_exit '> $x, where x null does not fail'
114*4887Schinexec <<!
115*4887Schinfoo
116*4887Schinbar
117*4887Schin!
118*4887Schin( exec 0< /dev/null)
119*4887Schinread line
120*4887Schinif	[[ $line != foo ]]
121*4887Schinthen	err_exit 'file descriptor not restored after exec in subshell'
122*4887Schinfi
123*4887Schinexec 3>&- 4>&-; cd /; rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed"
124*4887Schin[[ $( {
125*4887Schin	read -r line;print -r -- "$line"
126*4887Schin	(
127*4887Schin	        read -r line;print -r -- "$line"
128*4887Schin	) & wait
129*4887Schin	while	read -r line
130*4887Schin        do	print -r -- "$line"
131*4887Schin	done
132*4887Schin } << !
133*4887Schinline 1
134*4887Schinline 2
135*4887Schinline 3
136*4887Schin!) == $'line 1\nline 2\nline 3' ]] || err_exit 'read error with subshells'
137*4887Schin# 2004-05-11 bug fix
138*4887Schincat > /tmp/io$$.1 <<- \++EOF++
139*4887Schin	script=/tmp/io$$.2
140*4887Schin	trap 'rm -f $script' EXIT
141*4887Schin	exec 9> $script
142*4887Schin	for ((i=3; i<9; i++))
143*4887Schin	do	eval "while read -u$i; do : ;done $i</dev/null"
144*4887Schin		print -u9 "exec $i< /dev/null"
145*4887Schin	done
146*4887Schin	for ((i=0; i < 60; i++))
147*4887Schin	do	print -u9 -f "%.80c\n"  ' '
148*4887Schin	done
149*4887Schin	print -u9 'print ok'
150*4887Schin	exec 9<&-
151*4887Schin	chmod +x $script
152*4887Schin	$script
153*4887Schin++EOF++
154*4887Schinchmod +x /tmp/io$$.1
155*4887Schin[[ $($SHELL  /tmp/io$$.1) == ok ]]  || err_exit "parent i/o causes child script to fail"
156*4887Schinrm -rf /tmp/io$$.[12]
157*4887Schin# 2004-11-25 ancient /dev/fd/NN redirection bug fix
158*4887Schinx=$(
159*4887Schin	{
160*4887Schin		print -n 1
161*4887Schin		print -n 2 > /dev/fd/2
162*4887Schin		print -n 3
163*4887Schin		print -n 4 > /dev/fd/2
164*4887Schin	}  2>&1
165*4887Schin)
166*4887Schin[[ $x == "1234" ]] || err_exit "/dev/fd/NN redirection fails to dup"
167*4887Schin# 2004-12-20 redirction loss bug fix
168*4887Schincat > /tmp/io$$.1 <<- \++EOF++
169*4887Schin	function a
170*4887Schin	{
171*4887Schin		trap 'print ok' EXIT
172*4887Schin		: > /dev/null
173*4887Schin	}
174*4887Schin	a
175*4887Schin++EOF++
176*4887Schinchmod +x /tmp/io$$.1
177*4887Schin[[ $(/tmp/io$$.1) == ok ]] || err_exit "trap on EXIT loses last command redirection"
178*4887Schinprint > /dev/null {n}> /tmp/io$$.1
179*4887Schin[[ ! -s /tmp/io$$.1 ]] && newio=1
180*4887Schinrm -rf /tmp/io$$.1
181*4887Schinif	[[ $newio && $(print hello | while read -u$n; do print $REPLY; done {n}<&0) != hello ]]
182*4887Schinthen	err_exit "{n}<&0 not working with for loop"
183*4887Schinfi
184*4887Schin[[ $({ read -r;read -u3 3<&0; print -- "$REPLY" ;} <<!
185*4887Schinhello
186*4887Schinworld
187*4887Schin!) == world ]] || err_exit 'I/O not synchronized with <&'
188*4887Schintrap 'rm -f /tmp/seek$$; exit $((Errors+1))' EXIT
189*4887Schinx="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNSPQRSTUVWXYZ1234567890"
190*4887Schinfor ((i=0; i < 62; i++))
191*4887Schindo	printf "%.39c\n"  ${x:i:1}
192*4887Schindone >  /tmp/seek$$
193*4887Schinif	command exec 3<> /tmp/seek$$
194*4887Schinthen	(( $(3<#) == 0 )) || err_exit "not at position 0"
195*4887Schin	(( $(3<# ((EOF))) == 40*62 )) || err_exit "not at end-of-file"
196*4887Schin	command exec 3<# ((40*8)) || err_exit "absolute seek fails"
197*4887Schin	read -u3
198*4887Schin	[[ $REPLY == +(i) ]] || err_exit "expecting iiii..."
199*4887Schin	[[ $(3<#) == $(3<# ((CUR)) ) ]] || err_exit '$(3<#)!=$(3<#((CUR)))'
200*4887Schin	command exec 3<# ((CUR+80))
201*4887Schin	read -u3
202*4887Schin	[[ $REPLY == {39}(l) ]] || err_exit "expecting lll..."
203*4887Schin	command exec 3<# ((EOF-80))
204*4887Schin	read -u3
205*4887Schin	[[ $REPLY == +(9) ]] || err_exit "expecting 999...; got $REPLY"
206*4887Schin	command exec 3># ((80))
207*4887Schin	print -u3 -f "%.39c\n"  @
208*4887Schin	command exec 3># ((80))
209*4887Schin	read -u3
210*4887Schin	[[ $REPLY == +(@) ]] || err_exit "expecting @@@..."
211*4887Schin	read -u3
212*4887Schin	[[ $REPLY == +(d) ]] || err_exit "expecting ddd..."
213*4887Schin	command exec 3># ((EOF))
214*4887Schin	print -u3 -f "%.39c\n"  ^
215*4887Schin	(( $(3<# ((CUR-0))) == 40*63 )) || err_exit "not at extended end-of-file"
216*4887Schin	command exec 3<# ((40*62))
217*4887Schin	read -u3
218*4887Schin	[[ $REPLY == +(^) ]] || err_exit "expecting ddd..."
219*4887Schin	command exec 3<# ((0))
220*4887Schin	command exec 3<# *jjjj*
221*4887Schin	read -u3
222*4887Schin	[[  $REPLY == {39}(j) ]] || err_exit "<# pattern failed"
223*4887Schin	[[ $(command exec 3<## *llll*) = {39}(k) ]] || err_exit "<## pattern not saving standard output"
224*4887Schin	read -u3
225*4887Schin	[[  $REPLY == {39}(l) ]] || err_exit "<## pattern failed to position"
226*4887Schin	command exec 3<# *abc*
227*4887Schin	read -u3 && err_exit "not found pattern not positioning at eof"
228*4887Schin	cat /tmp/seek$$ | read -r <# *WWW*
229*4887Schin	[[ $REPLY == *WWWWW* ]] || err_exit '<# not working for pipes'
230*4887Schinelse	err_exit "/tmp/seek$$: cannot open for reading"
231*4887Schinfi
232*4887Schintrap "" EXIT
233*4887Schinrm -f  /tmp/seek$$
234*4887Schin$SHELL -ic '
235*4887Schin{
236*4887Schin    print -u2  || exit 2
237*4887Schin    print -u3  || exit 3
238*4887Schin    print -u4  || exit 4
239*4887Schin    print -u5  || exit 5
240*4887Schin    print -u6  || exit 6
241*4887Schin    print -u7  || exit 7
242*4887Schin    print -u8  || exit 8
243*4887Schin    print -u9  || exit 9
244*4887Schin}  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
245*4887Schinexitval=$?
246*4887Schin(( exitval ))  && err_exit  "print to unit $exitval failed"
247*4887Schintrap 'rm -rf /tmp/io.sh$$*' EXIT
248*4887Schin$SHELL -c "{ > /tmp/io.sh$$.1 ; date;} >&- 2> /dev/null" > /tmp/io.sh$$.2
249*4887Schin[[ -s /tmp/io.sh$$.1 || -s /tmp/io.sh$$.2 ]] && err_exit 'commands with standard output closed produce output'
250*4887Schin$SHELL -c "$SHELL -c ': 3>&1' 1>&- 2>/dev/null" && err_exit 'closed standard output not passed to subshell'
251*4887Schinexit $((Errors))
252