xref: /titanic_50/usr/src/lib/libshell/common/tests/io.sh (revision 4f680cc668fa6cf678c531083400ade9a9c7934c)
1########################################################################
2#                                                                      #
3#               This software is part of the ast package               #
4#          Copyright (c) 1982-2008 AT&T Intellectual Property          #
5#                      and is licensed under the                       #
6#                  Common Public License, Version 1.0                  #
7#                    by AT&T Intellectual Property                     #
8#                                                                      #
9#                A copy of the License is available at                 #
10#            http://www.opensource.org/licenses/cpl1.0.txt             #
11#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
12#                                                                      #
13#              Information and Software Systems Research               #
14#                            AT&T Research                             #
15#                           Florham Park NJ                            #
16#                                                                      #
17#                  David Korn <dgk@research.att.com>                   #
18#                                                                      #
19########################################################################
20function err_exit
21{
22	print -u2 -n "\t"
23	print -u2 -r ${Command}[$1]: "${@:2}"
24	let Errors+=1
25}
26alias err_exit='err_exit $LINENO'
27
28Command=${0##*/}
29integer Errors=0
30
31unset HISTFILE
32
33function fun
34{
35	while  command exec 3>&1
36	do	break
37	done 2>   /dev/null
38	print -u3 good
39}
40print 'read -r a;print -r -u$1 -- "$a"' >  /tmp/mycat$$
41chmod 755 /tmp/mycat$$
42for ((i=3; i < 10; i++))
43do
44	eval "a=\$(print foo | /tmp/mycat$$" $i $i'>&1 > /dev/null |cat)' 2> /dev/null
45	[[ $a == foo ]] || err_exit "bad file descriptor $i in comsub script"
46done
47rm -f /tmp/mycat$$
48exec 3> /dev/null
49[[ $(fun) == good ]] || err_exit 'file 3 closed before subshell completes'
50exec 3>&-
51mkdir /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed"
52trap 'rm -rf /tmp/ksh$$' EXIT
53cd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed"
54print foo > file1
55print bar >> file1
56if	[[ $(<file1) != $'foo\nbar' ]]
57then	err_exit 'append (>>) not working'
58fi
59set -o noclobber
60exec 3<> file1
61read -u3 line
62if	[[ $line != foo ]]
63then	err_exit '<> not working right with read'
64fi
65if	( 4> file1 ) 2> /dev/null
66then	err_exit 'noclobber not causing exclusive open'
67fi
68set +o noclobber
69if	command exec 4< /dev/fd/3
70then	read -u4 line
71	if	[[ $line != bar ]]
72	then	'4< /dev/fd/3 not working correctly'
73	fi
74fi
75cat > close0 <<\!
76exec 0<&-
77echo $(./close1)
78!
79print "echo abc" > close1
80chmod +x close0 close1
81x=$(./close0)
82if	[[ $x != "abc" ]]
83then	err_exit "picked up file descriptor zero for opening script file"
84fi
85cat > close0 <<\!
86	for ((i=0; i < 1100; i++))
87	do	exec 4< /dev/null
88		read -u4
89	done
90	exit 0
91!
92./close0 2> /dev/null || err_exit "multiple exec 4< /dev/null can fail"
93$SHELL -c '
94	trap "rm -f in$$ out$$" EXIT
95	for ((i = 0; i < 1000; i++))
96	do	print -r -- "This is a test"
97	done > in$$
98	> out$$
99	exec 1<> out$$
100	builtin cat
101	print -r -- "$(cat in$$)"
102	cmp -s in$$ out$$'  2> /dev/null
103[[ $? == 0 ]] || err_exit 'builtin cat truncates files'
104cat >| script <<-\!
105print hello
106( exec 3<&- 4<&-)
107exec 3<&- 4<&-
108print world
109!
110chmod +x script
111[[ $( $SHELL ./script) == $'hello\nworld' ]] || err_exit 'closing 3 & 4 causes script to fail'
112cd ~- || err_exit "cd back failed"
113( exec  > '' ) 2> /dev/null  && err_exit '> "" does not fail'
114unset x
115( exec > ${x} ) 2> /dev/null && err_exit '> $x, where x null does not fail'
116exec <<!
117foo
118bar
119!
120( exec 0< /dev/null)
121read line
122if	[[ $line != foo ]]
123then	err_exit 'file descriptor not restored after exec in subshell'
124fi
125exec 3>&- 4>&-; cd /; rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed"
126[[ $( {
127	read -r line;print -r -- "$line"
128	(
129	        read -r line;print -r -- "$line"
130	) & wait
131	while	read -r line
132        do	print -r -- "$line"
133	done
134 } << !
135line 1
136line 2
137line 3
138!) == $'line 1\nline 2\nline 3' ]] || err_exit 'read error with subshells'
139# 2004-05-11 bug fix
140cat > /tmp/io$$.1 <<- \++EOF++
141	script=/tmp/io$$.2
142	trap 'rm -f $script' EXIT
143	exec 9> $script
144	for ((i=3; i<9; i++))
145	do	eval "while read -u$i; do : ;done $i</dev/null"
146		print -u9 "exec $i< /dev/null"
147	done
148	for ((i=0; i < 60; i++))
149	do	print -u9 -f "%.80c\n"  ' '
150	done
151	print -u9 'print ok'
152	exec 9<&-
153	chmod +x $script
154	$script
155++EOF++
156chmod +x /tmp/io$$.1
157[[ $($SHELL  /tmp/io$$.1) == ok ]]  || err_exit "parent i/o causes child script to fail"
158rm -rf /tmp/io$$.[12]
159# 2004-11-25 ancient /dev/fd/NN redirection bug fix
160x=$(
161	{
162		print -n 1
163		print -n 2 > /dev/fd/2
164		print -n 3
165		print -n 4 > /dev/fd/2
166	}  2>&1
167)
168[[ $x == "1234" ]] || err_exit "/dev/fd/NN redirection fails to dup"
169# 2004-12-20 redirction loss bug fix
170cat > /tmp/io$$.1 <<- \++EOF++
171	function a
172	{
173		trap 'print ok' EXIT
174		: > /dev/null
175	}
176	a
177++EOF++
178chmod +x /tmp/io$$.1
179[[ $(/tmp/io$$.1) == ok ]] || err_exit "trap on EXIT loses last command redirection"
180print > /dev/null {n}> /tmp/io$$.1
181[[ ! -s /tmp/io$$.1 ]] && newio=1
182rm -rf /tmp/io$$.1
183if	[[ $newio && $(print hello | while read -u$n; do print $REPLY; done {n}<&0) != hello ]]
184then	err_exit "{n}<&0 not working with for loop"
185fi
186[[ $({ read -r;read -u3 3<&0; print -- "$REPLY" ;} <<!
187hello
188world
189!) == world ]] || err_exit 'I/O not synchronized with <&'
190trap 'rm -f /tmp/seek$$; exit $((Errors+1))' EXIT
191x="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNSPQRSTUVWXYZ1234567890"
192for ((i=0; i < 62; i++))
193do	printf "%.39c\n"  ${x:i:1}
194done >  /tmp/seek$$
195if	command exec 3<> /tmp/seek$$
196then	(( $(3<#) == 0 )) || err_exit "not at position 0"
197	(( $(3<# ((EOF))) == 40*62 )) || err_exit "not at end-of-file"
198	command exec 3<# ((40*8)) || err_exit "absolute seek fails"
199	read -u3
200	[[ $REPLY == +(i) ]] || err_exit "expecting iiii..."
201	[[ $(3<#) == $(3<# ((CUR)) ) ]] || err_exit '$(3<#)!=$(3<#((CUR)))'
202	command exec 3<# ((CUR+80))
203	read -u3
204	[[ $REPLY == {39}(l) ]] || err_exit "expecting lll..."
205	command exec 3<# ((EOF-80))
206	read -u3
207	[[ $REPLY == +(9) ]] || err_exit "expecting 999...; got $REPLY"
208	command exec 3># ((80))
209	print -u3 -f "%.39c\n"  @
210	command exec 3># ((80))
211	read -u3
212	[[ $REPLY == +(@) ]] || err_exit "expecting @@@..."
213	read -u3
214	[[ $REPLY == +(d) ]] || err_exit "expecting ddd..."
215	command exec 3># ((EOF))
216	print -u3 -f "%.39c\n"  ^
217	(( $(3<# ((CUR-0))) == 40*63 )) || err_exit "not at extended end-of-file"
218	command exec 3<# ((40*62))
219	read -u3
220	[[ $REPLY == +(^) ]] || err_exit "expecting ddd..."
221	command exec 3<# ((0))
222	command exec 3<# *jjjj*
223	read -u3
224	[[  $REPLY == {39}(j) ]] || err_exit "<# pattern failed"
225	[[ $(command exec 3<## *llll*) = {39}(k) ]] || err_exit "<## pattern not saving standard output"
226	read -u3
227	[[  $REPLY == {39}(l) ]] || err_exit "<## pattern failed to position"
228	command exec 3<# *abc*
229	read -u3 && err_exit "not found pattern not positioning at eof"
230	cat /tmp/seek$$ | read -r <# *WWW*
231	[[ $REPLY == *WWWWW* ]] || err_exit '<# not working for pipes'
232	{ < /tmp/seek$$ <# ((2358336120)) ;} 2> /dev/null || err_exit 'long seek not working'
233else	err_exit "/tmp/seek$$: cannot open for reading"
234fi
235command exec 3<&- || 'cannot close 3'
236for ((i=0; i < 62; i++))
237do	printf "%.39c\n"  ${x:i:1}
238done >  /tmp/seek$$
239if	command exec {n}<> /tmp/seek$$
240then	{ command exec {n}<#((EOF)) ;} 2> /dev/null || err_exit '{n}<# not working'
241	if	$SHELL -c '{n}</dev/null' 2> /dev/null
242	then	(( $({n}<#) ==  40*62))  || err_exit '$({n}<#) not working'
243	else	err_exit 'not able to parse {n}</dev/null'
244	fi
245fi
246trap "" EXIT
247rm -f  /tmp/seek$$
248$SHELL -ic '
249{
250    print -u2  || exit 2
251    print -u3  || exit 3
252    print -u4  || exit 4
253    print -u5  || exit 5
254    print -u6  || exit 6
255    print -u7  || exit 7
256    print -u8  || exit 8
257    print -u9  || exit 9
258}  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
259exitval=$?
260(( exitval ))  && err_exit  "print to unit $exitval failed"
261trap 'rm -rf /tmp/io.sh$$*' EXIT
262$SHELL -c "{ > /tmp/io.sh$$.1 ; date;} >&- 2> /dev/null" > /tmp/io.sh$$.2
263[[ -s /tmp/io.sh$$.1 || -s /tmp/io.sh$$.2 ]] && err_exit 'commands with standard output closed produce output'
264$SHELL -c "$SHELL -c ': 3>&1' 1>&- 2>/dev/null" && err_exit 'closed standard output not passed to subshell'
265[[ $(cat  <<- \EOF | $SHELL
266	do_it_all()
267	{
268	 	dd 2>/dev/null  # not a ksh93 buildin
269	 	return $?
270	}
271	do_it_all ; exit $?
272	hello world
273EOF) == 'hello world' ]] || err_exit 'invalid readahead on stdin'
274$SHELL -c 'exec 3>; /dev/null'  2> /dev/null && err_exit '>; with exec should be an error'
275$SHELL -c ': 3>; /dev/null'  2> /dev/null || err_exit '>; not working with at all'
276print hello > /tmp/io.sh$$.1
277if	! $SHELL -c "false >; /tmp/io.sh$$.1"  2> /dev/null
278then	[[ $(</tmp/io.sh$$.1) == hello ]] || err_exit '>; not preserving file on failure'
279fi
280if	! $SHELL -c "sed -e 's/hello/hello world/' /tmp/io.sh$$.1" >; /tmp/io.sh$$.1  2> /dev/null
281then	[[ $(</tmp/io.sh$$.1) == 'hello world' ]] || err_exit '>; not updating file on success'
282fi
283
284unset y
285read -n1 y <<!
286abc
287!
288if      [[ $y != a ]]
289then    err_exit  'read -n1 not working'
290fi
291unset a
292{ read -N3 a; read -N1 b;}  <<!
293abcdefg
294!
295[[ $a == abc ]] || err_exit 'read -N3 here-document not working'
296[[ $b == d ]] || err_exit 'read -N1 here-document not working'
297read -n3 a <<!
298abcdefg
299!
300[[ $a == abc ]] || err_exit 'read -n3 here-document not working'
301(print -n a;sleep 1; print -n bcde) | { read -N3 a; read -N1 b;}
302[[ $a == abc ]] || err_exit 'read -N3 from pipe not working'
303[[ $b == d ]] || err_exit 'read -N1 from pipe not working'
304(print -n a;sleep 1; print -n bcde) |read -n3 a
305[[ $a == a ]] || err_exit 'read -n3 from pipe not working'
306rm -f /tmp/fifo$$
307if	mkfifo /tmp/fifo$$ 2> /dev/null
308then	(print -n a; sleep 1;print -n bcde)  > /tmp/fifo$$ &
309	{
310	read -u5 -n3  -t2 a  || err_exit 'read -n3 from fifo timedout'
311	read -u5 -n1 -t2 b || err_exit 'read -n1 from fifo timedout'
312	} 5< /tmp/fifo$$
313	[[ $a == a ]] || err_exit 'read -n3 from fifo not working'
314	rm -f /tmp/fifo$$
315	mkfifo /tmp/fifo$$ 2> /dev/null
316	(print -n a; sleep 1;print -n bcde)  > /tmp/fifo$$ &
317	{
318	read -u5 -N3 -t2 a || err_exit 'read -N3 from fifo timed out'
319	read -u5 -N1 -t2 b || err_exit 'read -N1 from fifo timedout'
320	} 5< /tmp/fifo$$
321	[[ $a == abc ]] || err_exit 'read -N3 from fifo not working'
322	[[ $b == d ]] || err_exit 'read -N1 from fifo not working'
323fi
324rm -f /tmp/fifo$$
325
326if	$SHELL -c "export LC_ALL=en_US.UTF-8; c=$'\342\202\254'; [[ \${#c} == 1 ]]" 2>/dev/null
327then	lc_utf8=en_US.UTF-8
328else	lc_utf8=''
329fi
330
331typeset -a e o=(-n2 -N2)
332integer i
333set -- \
334	'a'	'bcd'	'a bcd'	'ab cd' \
335	'ab'	'cd'	'ab cd'	'ab cd' \
336	'abc'	'd'	'ab cd'	'ab cd' \
337	'abcd'	''	'ab cd'	'ab cd'
338while	(( $# >= 3 ))
339do	a=$1
340	b=$2
341	e[0]=$3
342	e[1]=$4
343	shift 4
344	for ((i = 0; i < 2; i++))
345	do	for lc_all in C $lc_utf8
346		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			[[ $g == "${e[i]}" ]] || err_exit "LC_ALL=$lc_all read ${o[i]} from pipe '$a $b' failed -- expected '${e[i]}', got '$g'"
348		done
349	done
350done
351
352if	[[ $lc_utf8 ]]
353then	export LC_ALL=en_US.UTF-8
354	typeset -a c=( '' 'A' $'\303\274' $'\342\202\254' )
355	integer i w
356	typeset o
357	if	(( ${#c[2]} == 1 && ${#c[3]} == 1 ))
358	then	for i in 1 2 3
359		do	for o in n N
360			do	for w in 1 2 3
361				do	print -nr "${c[w]}" | read -${o}${i} g
362					if	[[ $o == N ]] && (( i > 1 ))
363					then	e=''
364					else	e=${c[w]}
365					fi
366					[[ $g == "$e" ]] || err_exit "read -${o}${i} failed for '${c[w]}' -- expected '$e', got '$g'"
367				done
368			done
369		done
370	fi
371fi
372
373exit $((Errors))
374