xref: /titanic_51/usr/src/lib/libshell/common/tests/io.sh (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin########################################################################
2da2e3ebdSchin#                                                                      #
3da2e3ebdSchin#               This software is part of the ast package               #
4*3e14f97fSRoger A. Faulkner#          Copyright (c) 1982-2010 AT&T Intellectual Property          #
5da2e3ebdSchin#                      and is licensed under the                       #
6da2e3ebdSchin#                  Common Public License, Version 1.0                  #
77c2fbfb3SApril Chin#                    by AT&T Intellectual Property                     #
8da2e3ebdSchin#                                                                      #
9da2e3ebdSchin#                A copy of the License is available at                 #
10da2e3ebdSchin#            http://www.opensource.org/licenses/cpl1.0.txt             #
11da2e3ebdSchin#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
12da2e3ebdSchin#                                                                      #
13da2e3ebdSchin#              Information and Software Systems Research               #
14da2e3ebdSchin#                            AT&T Research                             #
15da2e3ebdSchin#                           Florham Park NJ                            #
16da2e3ebdSchin#                                                                      #
17da2e3ebdSchin#                  David Korn <dgk@research.att.com>                   #
18da2e3ebdSchin#                                                                      #
19da2e3ebdSchin########################################################################
20da2e3ebdSchinfunction err_exit
21da2e3ebdSchin{
22da2e3ebdSchin	print -u2 -n "\t"
23da2e3ebdSchin	print -u2 -r ${Command}[$1]: "${@:2}"
24da2e3ebdSchin	let Errors+=1
25da2e3ebdSchin}
26da2e3ebdSchinalias err_exit='err_exit $LINENO'
27da2e3ebdSchin
28da2e3ebdSchinCommand=${0##*/}
29da2e3ebdSchininteger Errors=0
307c2fbfb3SApril Chin
3134f9b3eeSRoland Mainztmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
3234f9b3eeSRoland Mainztrap "cd /; rm -rf $tmp" EXIT
3334f9b3eeSRoland Mainz
347c2fbfb3SApril Chinunset HISTFILE
357c2fbfb3SApril Chin
36da2e3ebdSchinfunction fun
37da2e3ebdSchin{
38da2e3ebdSchin	while  command exec 3>&1
39da2e3ebdSchin	do	break
40da2e3ebdSchin	done 2>   /dev/null
41da2e3ebdSchin	print -u3 good
42da2e3ebdSchin}
4334f9b3eeSRoland Mainzprint 'read -r a;print -r -u$1 -- "$a"' > $tmp/mycat
4434f9b3eeSRoland Mainzchmod 755 $tmp/mycat
45da2e3ebdSchinfor ((i=3; i < 10; i++))
46da2e3ebdSchindo
4734f9b3eeSRoland Mainz	eval "a=\$(print foo | $tmp/mycat" $i $i'>&1 > /dev/null |cat)' 2> /dev/null
48da2e3ebdSchin	[[ $a == foo ]] || err_exit "bad file descriptor $i in comsub script"
49da2e3ebdSchindone
50da2e3ebdSchinexec 3> /dev/null
51da2e3ebdSchin[[ $(fun) == good ]] || err_exit 'file 3 closed before subshell completes'
52da2e3ebdSchinexec 3>&-
5334f9b3eeSRoland Mainzcd $tmp || { err_exit "cd $tmp failed"; exit ; }
54da2e3ebdSchinprint foo > file1
55da2e3ebdSchinprint bar >> file1
56da2e3ebdSchinif	[[ $(<file1) != $'foo\nbar' ]]
57da2e3ebdSchinthen	err_exit 'append (>>) not working'
58da2e3ebdSchinfi
59da2e3ebdSchinset -o noclobber
60da2e3ebdSchinexec 3<> file1
61da2e3ebdSchinread -u3 line
6234f9b3eeSRoland Mainzexp=foo
6334f9b3eeSRoland Mainzif	[[ $line != $exp ]]
6434f9b3eeSRoland Mainzthen	err_exit "read on <> fd failed -- expected '$exp', got '$line'"
65da2e3ebdSchinfi
66da2e3ebdSchinif	( 4> file1 ) 2> /dev/null
67da2e3ebdSchinthen	err_exit 'noclobber not causing exclusive open'
68da2e3ebdSchinfi
69da2e3ebdSchinset +o noclobber
7034f9b3eeSRoland Mainz
7134f9b3eeSRoland MainzFDFS=(
7234f9b3eeSRoland Mainz	( dir=/proc/self/fd	semantics='open'	)
7334f9b3eeSRoland Mainz	( dir=/proc/$$/fd	semantics='open'	)
7434f9b3eeSRoland Mainz	( dir=/dev/fd		semantics='open|dup'	)
7534f9b3eeSRoland Mainz	( dir=/dev/fd		semantics='dup'	)
7634f9b3eeSRoland Mainz)
7734f9b3eeSRoland Mainzfor ((fdfs=0; fdfs<${#FDFS[@]}-1; fdfs++))
7834f9b3eeSRoland Mainzdo	[[ -e ${FDFS[fdfs].dir} ]] && { command : > ${FDFS[fdfs].dir}/1; } 2>/dev/null && break
7934f9b3eeSRoland Mainzdone
8034f9b3eeSRoland Mainz
8134f9b3eeSRoland Mainzexec 3<> file1
8234f9b3eeSRoland Mainzif	command exec 4< ${FDFS[fdfs].dir}/3
8334f9b3eeSRoland Mainzthen	read -u3 got
8434f9b3eeSRoland Mainz	read -u4 got
8534f9b3eeSRoland Mainz	exp='foo|bar'
8634f9b3eeSRoland Mainz	case $got in
8734f9b3eeSRoland Mainz	foo)	semantics='open' ;;
8834f9b3eeSRoland Mainz	bar)	semantics='dup' ;;
8934f9b3eeSRoland Mainz	*)	semantics='failed' ;;
9034f9b3eeSRoland Mainz	esac
9134f9b3eeSRoland Mainz	[[ $semantics == @(${FDFS[fdfs].semantics}) ]] || err_exit "'4< ${FDFS[fdfs].dir}/3' $semantics semantics instead of ${FDFS[fdfs].semantics} -- expected '$exp', got '$got'"
92da2e3ebdSchinfi
9334f9b3eeSRoland Mainz
9434f9b3eeSRoland Mainz# 2004-11-25 ancient /dev/fd/N redirection bug fix
9534f9b3eeSRoland Mainzgot=$(
9634f9b3eeSRoland Mainz	{
9734f9b3eeSRoland Mainz		print -n 1
9834f9b3eeSRoland Mainz		print -n 2 > ${FDFS[fdfs].dir}/2
9934f9b3eeSRoland Mainz		print -n 3
10034f9b3eeSRoland Mainz		print -n 4 > ${FDFS[fdfs].dir}/2
10134f9b3eeSRoland Mainz	}  2>&1
10234f9b3eeSRoland Mainz)
10334f9b3eeSRoland Mainzexp='1234|4'
10434f9b3eeSRoland Mainzcase $got in
10534f9b3eeSRoland Mainz1234)	semantics='dup' ;;
10634f9b3eeSRoland Mainz4)	semantics='open' ;;
10734f9b3eeSRoland Mainz*)	semantics='failed' ;;
10834f9b3eeSRoland Mainzesac
10934f9b3eeSRoland Mainz[[ $semantics == @(${FDFS[fdfs].semantics}) ]] || err_exit "${FDFS[fdfs].dir}/N $semantics semantics instead of ${FDFS[fdfs].semantics} -- expected '$exp', got '$got'"
11034f9b3eeSRoland Mainz
111da2e3ebdSchincat > close0 <<\!
112da2e3ebdSchinexec 0<&-
113da2e3ebdSchinecho $(./close1)
114da2e3ebdSchin!
115da2e3ebdSchinprint "echo abc" > close1
116da2e3ebdSchinchmod +x close0 close1
117da2e3ebdSchinx=$(./close0)
118da2e3ebdSchinif	[[ $x != "abc" ]]
119da2e3ebdSchinthen	err_exit "picked up file descriptor zero for opening script file"
120da2e3ebdSchinfi
121da2e3ebdSchincat > close0 <<\!
122da2e3ebdSchin	for ((i=0; i < 1100; i++))
123da2e3ebdSchin	do	exec 4< /dev/null
124da2e3ebdSchin		read -u4
125da2e3ebdSchin	done
126da2e3ebdSchin	exit 0
127da2e3ebdSchin!
128da2e3ebdSchin./close0 2> /dev/null || err_exit "multiple exec 4< /dev/null can fail"
129da2e3ebdSchin$SHELL -c '
13034f9b3eeSRoland Mainz	trap "rm -f in out" EXIT
131da2e3ebdSchin	for ((i = 0; i < 1000; i++))
132da2e3ebdSchin	do	print -r -- "This is a test"
13334f9b3eeSRoland Mainz	done > in
13434f9b3eeSRoland Mainz	> out
13534f9b3eeSRoland Mainz	exec 1<> out
136da2e3ebdSchin	builtin cat
13734f9b3eeSRoland Mainz	print -r -- "$(<in)"
13834f9b3eeSRoland Mainz	cmp -s in out'  2> /dev/null
139da2e3ebdSchin[[ $? == 0 ]] || err_exit 'builtin cat truncates files'
140da2e3ebdSchincat >| script <<-\!
141da2e3ebdSchinprint hello
142da2e3ebdSchin( exec 3<&- 4<&-)
143da2e3ebdSchinexec 3<&- 4<&-
144da2e3ebdSchinprint world
145da2e3ebdSchin!
146da2e3ebdSchinchmod +x script
147da2e3ebdSchin[[ $( $SHELL ./script) == $'hello\nworld' ]] || err_exit 'closing 3 & 4 causes script to fail'
148da2e3ebdSchincd ~- || err_exit "cd back failed"
149da2e3ebdSchin( exec  > '' ) 2> /dev/null  && err_exit '> "" does not fail'
150da2e3ebdSchinunset x
151da2e3ebdSchin( exec > ${x} ) 2> /dev/null && err_exit '> $x, where x null does not fail'
152da2e3ebdSchinexec <<!
153da2e3ebdSchinfoo
154da2e3ebdSchinbar
155da2e3ebdSchin!
156da2e3ebdSchin( exec 0< /dev/null)
157da2e3ebdSchinread line
158da2e3ebdSchinif	[[ $line != foo ]]
159da2e3ebdSchinthen	err_exit 'file descriptor not restored after exec in subshell'
160da2e3ebdSchinfi
16134f9b3eeSRoland Mainzexec 3>&- 4>&-
162da2e3ebdSchin[[ $( {
163da2e3ebdSchin	read -r line;print -r -- "$line"
164da2e3ebdSchin	(
165da2e3ebdSchin	        read -r line;print -r -- "$line"
166da2e3ebdSchin	) & wait
167da2e3ebdSchin	while	read -r line
168da2e3ebdSchin        do	print -r -- "$line"
169da2e3ebdSchin	done
170da2e3ebdSchin } << !
171da2e3ebdSchinline 1
172da2e3ebdSchinline 2
173da2e3ebdSchinline 3
174da2e3ebdSchin!) == $'line 1\nline 2\nline 3' ]] || err_exit 'read error with subshells'
175da2e3ebdSchin# 2004-05-11 bug fix
17634f9b3eeSRoland Mainzcat > $tmp/1 <<- ++EOF++
17734f9b3eeSRoland Mainz	script=$tmp/2
17834f9b3eeSRoland Mainz	trap "rm -f \$script" EXIT
17934f9b3eeSRoland Mainz	exec 9> \$script
180da2e3ebdSchin	for ((i=3; i<9; i++))
18134f9b3eeSRoland Mainz	do	eval "while read -u\$i; do : ;done \$i</dev/null"
18234f9b3eeSRoland Mainz		print -u9 "exec \$i< /dev/null"
183da2e3ebdSchin	done
184da2e3ebdSchin	for ((i=0; i < 60; i++))
185da2e3ebdSchin	do	print -u9 -f "%.80c\n"  ' '
186da2e3ebdSchin	done
187da2e3ebdSchin	print -u9 'print ok'
188da2e3ebdSchin	exec 9<&-
18934f9b3eeSRoland Mainz	chmod +x \$script
19034f9b3eeSRoland Mainz	\$script
191da2e3ebdSchin++EOF++
19234f9b3eeSRoland Mainzchmod +x $tmp/1
19334f9b3eeSRoland Mainz[[ $($SHELL  $tmp/1) == ok ]]  || err_exit "parent i/o causes child script to fail"
19434f9b3eeSRoland Mainz# 2004-12-20 redirection loss bug fix
19534f9b3eeSRoland Mainzcat > $tmp/1 <<- \++EOF++
196da2e3ebdSchin	function a
197da2e3ebdSchin	{
198da2e3ebdSchin		trap 'print ok' EXIT
199da2e3ebdSchin		: > /dev/null
200da2e3ebdSchin	}
201da2e3ebdSchin	a
202da2e3ebdSchin++EOF++
20334f9b3eeSRoland Mainzchmod +x $tmp/1
20434f9b3eeSRoland Mainz[[ $($tmp/1) == ok ]] || err_exit "trap on EXIT loses last command redirection"
20534f9b3eeSRoland Mainzprint > /dev/null {n}> $tmp/1
20634f9b3eeSRoland Mainz[[ ! -s $tmp/1 ]] && newio=1
207da2e3ebdSchinif	[[ $newio && $(print hello | while read -u$n; do print $REPLY; done {n}<&0) != hello ]]
208da2e3ebdSchinthen	err_exit "{n}<&0 not working with for loop"
209da2e3ebdSchinfi
210da2e3ebdSchin[[ $({ read -r;read -u3 3<&0; print -- "$REPLY" ;} <<!
211da2e3ebdSchinhello
212da2e3ebdSchinworld
213da2e3ebdSchin!) == world ]] || err_exit 'I/O not synchronized with <&'
214da2e3ebdSchinx="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNSPQRSTUVWXYZ1234567890"
215da2e3ebdSchinfor ((i=0; i < 62; i++))
216da2e3ebdSchindo	printf "%.39c\n"  ${x:i:1}
21734f9b3eeSRoland Mainzdone >  $tmp/seek
21834f9b3eeSRoland Mainzif	command exec 3<> $tmp/seek
219da2e3ebdSchinthen	(( $(3<#) == 0 )) || err_exit "not at position 0"
220da2e3ebdSchin	(( $(3<# ((EOF))) == 40*62 )) || err_exit "not at end-of-file"
221da2e3ebdSchin	command exec 3<# ((40*8)) || err_exit "absolute seek fails"
222da2e3ebdSchin	read -u3
22334f9b3eeSRoland Mainz	[[ $REPLY == +(i) ]] || err_exit "expected iiii..., got $REPLY"
224da2e3ebdSchin	[[ $(3<#) == $(3<# ((CUR)) ) ]] || err_exit '$(3<#)!=$(3<#((CUR)))'
225da2e3ebdSchin	command exec 3<# ((CUR+80))
226da2e3ebdSchin	read -u3
22734f9b3eeSRoland Mainz	[[ $REPLY == {39}(l) ]] || err_exit "expected lll..., got $REPLY"
228da2e3ebdSchin	command exec 3<# ((EOF-80))
229da2e3ebdSchin	read -u3
23034f9b3eeSRoland Mainz	[[ $REPLY == +(9) ]] || err_exit "expected 999..., got $REPLY"
231da2e3ebdSchin	command exec 3># ((80))
232da2e3ebdSchin	print -u3 -f "%.39c\n"  @
233da2e3ebdSchin	command exec 3># ((80))
234da2e3ebdSchin	read -u3
23534f9b3eeSRoland Mainz	[[ $REPLY == +(@) ]] || err_exit "expected @@@..., got $REPLY"
236da2e3ebdSchin	read -u3
23734f9b3eeSRoland Mainz	[[ $REPLY == +(d) ]] || err_exit "expected ddd..., got $REPLY"
238da2e3ebdSchin	command exec 3># ((EOF))
239da2e3ebdSchin	print -u3 -f "%.39c\n"  ^
240da2e3ebdSchin	(( $(3<# ((CUR-0))) == 40*63 )) || err_exit "not at extended end-of-file"
241da2e3ebdSchin	command exec 3<# ((40*62))
242da2e3ebdSchin	read -u3
24334f9b3eeSRoland Mainz	[[ $REPLY == +(^) ]] || err_exit "expected ddd..., got $REPLY"
244da2e3ebdSchin	command exec 3<# ((0))
245da2e3ebdSchin	command exec 3<# *jjjj*
246da2e3ebdSchin	read -u3
247da2e3ebdSchin	[[  $REPLY == {39}(j) ]] || err_exit "<# pattern failed"
248da2e3ebdSchin	[[ $(command exec 3<## *llll*) = {39}(k) ]] || err_exit "<## pattern not saving standard output"
249da2e3ebdSchin	read -u3
250da2e3ebdSchin	[[  $REPLY == {39}(l) ]] || err_exit "<## pattern failed to position"
251da2e3ebdSchin	command exec 3<# *abc*
252da2e3ebdSchin	read -u3 && err_exit "not found pattern not positioning at eof"
25334f9b3eeSRoland Mainz	cat $tmp/seek | read -r <# *WWW*
254da2e3ebdSchin	[[ $REPLY == *WWWWW* ]] || err_exit '<# not working for pipes'
25534f9b3eeSRoland Mainz	{ < $tmp/seek <# ((2358336120)) ;} 2> /dev/null || err_exit 'long seek not working'
25634f9b3eeSRoland Mainzelse	err_exit "$tmp/seek: cannot open for reading"
257da2e3ebdSchinfi
2587c2fbfb3SApril Chincommand exec 3<&- || 'cannot close 3'
2597c2fbfb3SApril Chinfor ((i=0; i < 62; i++))
2607c2fbfb3SApril Chindo	printf "%.39c\n"  ${x:i:1}
26134f9b3eeSRoland Mainzdone >  $tmp/seek
26234f9b3eeSRoland Mainzif	command exec {n}<> $tmp/seek
2637c2fbfb3SApril Chinthen	{ command exec {n}<#((EOF)) ;} 2> /dev/null || err_exit '{n}<# not working'
2647c2fbfb3SApril Chin	if	$SHELL -c '{n}</dev/null' 2> /dev/null
2657c2fbfb3SApril Chin	then	(( $({n}<#) ==  40*62))  || err_exit '$({n}<#) not working'
2667c2fbfb3SApril Chin	else	err_exit 'not able to parse {n}</dev/null'
2677c2fbfb3SApril Chin	fi
2687c2fbfb3SApril Chinfi
269da2e3ebdSchin$SHELL -ic '
270da2e3ebdSchin{
271da2e3ebdSchin    print -u2  || exit 2
272da2e3ebdSchin    print -u3  || exit 3
273da2e3ebdSchin    print -u4  || exit 4
274da2e3ebdSchin    print -u5  || exit 5
275da2e3ebdSchin    print -u6  || exit 6
276da2e3ebdSchin    print -u7  || exit 7
277da2e3ebdSchin    print -u8  || exit 8
278da2e3ebdSchin    print -u9  || exit 9
279da2e3ebdSchin}  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
280da2e3ebdSchinexitval=$?
281da2e3ebdSchin(( exitval ))  && err_exit  "print to unit $exitval failed"
28234f9b3eeSRoland Mainz$SHELL -c "{ > $tmp/1 ; date;} >&- 2> /dev/null" > $tmp/2
28334f9b3eeSRoland Mainz[[ -s $tmp/1 || -s $tmp/2 ]] && err_exit 'commands with standard output closed produce output'
284da2e3ebdSchin$SHELL -c "$SHELL -c ': 3>&1' 1>&- 2>/dev/null" && err_exit 'closed standard output not passed to subshell'
2857c2fbfb3SApril Chin[[ $(cat  <<- \EOF | $SHELL
2867c2fbfb3SApril Chin	do_it_all()
2877c2fbfb3SApril Chin	{
2887c2fbfb3SApril Chin	 	dd 2>/dev/null  # not a ksh93 buildin
2897c2fbfb3SApril Chin	 	return $?
2907c2fbfb3SApril Chin	}
2917c2fbfb3SApril Chin	do_it_all ; exit $?
2927c2fbfb3SApril Chin	hello world
2937c2fbfb3SApril ChinEOF) == 'hello world' ]] || err_exit 'invalid readahead on stdin'
2947c2fbfb3SApril Chin$SHELL -c 'exec 3>; /dev/null'  2> /dev/null && err_exit '>; with exec should be an error'
2957c2fbfb3SApril Chin$SHELL -c ': 3>; /dev/null'  2> /dev/null || err_exit '>; not working with at all'
29634f9b3eeSRoland Mainzprint hello > $tmp/1
29734f9b3eeSRoland Mainzif	! $SHELL -c "false >; $tmp/1"  2> /dev/null
29834f9b3eeSRoland Mainzthen	[[ $(<$tmp/1) == hello ]] || err_exit '>; not preserving file on failure'
2997c2fbfb3SApril Chinfi
30034f9b3eeSRoland Mainzif	! $SHELL -c "sed -e 's/hello/hello world/' $tmp/1" >; $tmp/1  2> /dev/null
30134f9b3eeSRoland Mainzthen	[[ $(<$tmp/1) == 'hello world' ]] || err_exit '>; not updating file on success'
30234f9b3eeSRoland Mainzfi
30334f9b3eeSRoland Mainz
30434f9b3eeSRoland Mainz$SHELL -c 'exec 3<>; /dev/null'  2> /dev/null && err_exit '<>; with exec should be an error'
30534f9b3eeSRoland Mainz$SHELL -c ': 3<>; /dev/null'  2> /dev/null || err_exit '<>; not working with at all'
30634f9b3eeSRoland Mainzprint $'hello\nworld' > $tmp/1
30734f9b3eeSRoland Mainzif      ! $SHELL -c "false <>; $tmp/1"  2> /dev/null
30834f9b3eeSRoland Mainzthen    [[ $(<$tmp/1) == $'hello\nworld' ]] || err_exit '<>; not preserving file on failure'
30934f9b3eeSRoland Mainzfi
31034f9b3eeSRoland Mainzif	! $SHELL -c "head -1 $tmp/1" <>; $tmp/1  2> /dev/null
31134f9b3eeSRoland Mainzthen	[[ $(<$tmp/1) == hello ]] || err_exit '<>; not truncating file on success of head'
31234f9b3eeSRoland Mainzfi
31334f9b3eeSRoland Mainzprint $'hello\nworld' > $tmp/1
31434f9b3eeSRoland Mainzif	! $SHELL -c head  < $tmp/1 <#((6)) <>; $tmp/1  2> /dev/null
31534f9b3eeSRoland Mainzthen	[[ $(<$tmp/1) == world ]] || err_exit '<>; not truncating file on success of behead'
3167c2fbfb3SApril Chinfi
3177c2fbfb3SApril Chin
3187c2fbfb3SApril Chinunset y
3197c2fbfb3SApril Chinread -n1 y <<!
3207c2fbfb3SApril Chinabc
3217c2fbfb3SApril Chin!
3227c2fbfb3SApril Chinif      [[ $y != a ]]
3237c2fbfb3SApril Chinthen    err_exit  'read -n1 not working'
3247c2fbfb3SApril Chinfi
3257c2fbfb3SApril Chinunset a
3267c2fbfb3SApril Chin{ read -N3 a; read -N1 b;}  <<!
3277c2fbfb3SApril Chinabcdefg
3287c2fbfb3SApril Chin!
3297c2fbfb3SApril Chin[[ $a == abc ]] || err_exit 'read -N3 here-document not working'
3307c2fbfb3SApril Chin[[ $b == d ]] || err_exit 'read -N1 here-document not working'
3317c2fbfb3SApril Chinread -n3 a <<!
3327c2fbfb3SApril Chinabcdefg
3337c2fbfb3SApril Chin!
3347c2fbfb3SApril Chin[[ $a == abc ]] || err_exit 'read -n3 here-document not working'
3357c2fbfb3SApril Chin(print -n a;sleep 1; print -n bcde) | { read -N3 a; read -N1 b;}
3367c2fbfb3SApril Chin[[ $a == abc ]] || err_exit 'read -N3 from pipe not working'
3377c2fbfb3SApril Chin[[ $b == d ]] || err_exit 'read -N1 from pipe not working'
3387c2fbfb3SApril Chin(print -n a;sleep 1; print -n bcde) |read -n3 a
3397c2fbfb3SApril Chin[[ $a == a ]] || err_exit 'read -n3 from pipe not working'
34034f9b3eeSRoland Mainzif	mkfifo $tmp/fifo 2> /dev/null
34134f9b3eeSRoland Mainzthen	(print -n a; sleep 1;print -n bcde)  > $tmp/fifo &
3427c2fbfb3SApril Chin	{
3437c2fbfb3SApril Chin	read -u5 -n3  -t2 a  || err_exit 'read -n3 from fifo timedout'
3447c2fbfb3SApril Chin	read -u5 -n1 -t2 b || err_exit 'read -n1 from fifo timedout'
34534f9b3eeSRoland Mainz	} 5< $tmp/fifo
3467c2fbfb3SApril Chin	[[ $a == a ]] || err_exit 'read -n3 from fifo not working'
34734f9b3eeSRoland Mainz	rm -f $tmp/fifo
34834f9b3eeSRoland Mainz	mkfifo $tmp/fifo 2> /dev/null
34934f9b3eeSRoland Mainz	(print -n a; sleep 1;print -n bcde)  > $tmp/fifo &
3507c2fbfb3SApril Chin	{
3517c2fbfb3SApril Chin	read -u5 -N3 -t2 a || err_exit 'read -N3 from fifo timed out'
3527c2fbfb3SApril Chin	read -u5 -N1 -t2 b || err_exit 'read -N1 from fifo timedout'
35334f9b3eeSRoland Mainz	} 5< $tmp/fifo
3547c2fbfb3SApril Chin	[[ $a == abc ]] || err_exit 'read -N3 from fifo not working'
3557c2fbfb3SApril Chin	[[ $b == d ]] || err_exit 'read -N1 from fifo not working'
3567c2fbfb3SApril Chinfi
35734f9b3eeSRoland Mainz(
35834f9b3eeSRoland Mainz	print -n 'prompt1: '
35934f9b3eeSRoland Mainz	sleep .1
36034f9b3eeSRoland Mainz	print line2
36134f9b3eeSRoland Mainz	sleep .1
36234f9b3eeSRoland Mainz	print -n 'prompt2: '
36334f9b3eeSRoland Mainz	sleep .1
36434f9b3eeSRoland Mainz) | {
36534f9b3eeSRoland Mainz	read -t2 -n 1000 line1
36634f9b3eeSRoland Mainz	read -t2 -n 1000 line2
36734f9b3eeSRoland Mainz	read -t2 -n 1000 line3
36834f9b3eeSRoland Mainz	read -t2 -n 1000 line4
36934f9b3eeSRoland Mainz}
370*3e14f97fSRoger A. Faulkner[[ $? == 0 ]]		 	&& err_exit 'should have timed out'
37134f9b3eeSRoland Mainz[[ $line1 == 'prompt1: ' ]] 	|| err_exit "line1 should be 'prompt1: '"
37234f9b3eeSRoland Mainz[[ $line2 == line2 ]]		|| err_exit "line2 should be line2"
37334f9b3eeSRoland Mainz[[ $line3 == 'prompt2: ' ]]	|| err_exit "line3 should be 'prompt2: '"
37434f9b3eeSRoland Mainz[[ ! $line4 ]]			|| err_exit "line4 should be empty"
3757c2fbfb3SApril Chin
3767c2fbfb3SApril Chinif	$SHELL -c "export LC_ALL=en_US.UTF-8; c=$'\342\202\254'; [[ \${#c} == 1 ]]" 2>/dev/null
3777c2fbfb3SApril Chinthen	lc_utf8=en_US.UTF-8
3787c2fbfb3SApril Chinelse	lc_utf8=''
3797c2fbfb3SApril Chinfi
3807c2fbfb3SApril Chin
3817c2fbfb3SApril Chintypeset -a e o=(-n2 -N2)
3827c2fbfb3SApril Chininteger i
3837c2fbfb3SApril Chinset -- \
3847c2fbfb3SApril Chin	'a'	'bcd'	'a bcd'	'ab cd' \
3857c2fbfb3SApril Chin	'ab'	'cd'	'ab cd'	'ab cd' \
3867c2fbfb3SApril Chin	'abc'	'd'	'ab cd'	'ab cd' \
3877c2fbfb3SApril Chin	'abcd'	''	'ab cd'	'ab cd'
3887c2fbfb3SApril Chinwhile	(( $# >= 3 ))
3897c2fbfb3SApril Chindo	a=$1
3907c2fbfb3SApril Chin	b=$2
3917c2fbfb3SApril Chin	e[0]=$3
3927c2fbfb3SApril Chin	e[1]=$4
3937c2fbfb3SApril Chin	shift 4
3947c2fbfb3SApril Chin	for ((i = 0; i < 2; i++))
3957c2fbfb3SApril Chin	do	for lc_all in C $lc_utf8
3967c2fbfb3SApril Chin		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; }")
3977c2fbfb3SApril Chin			[[ $g == "${e[i]}" ]] || err_exit "LC_ALL=$lc_all read ${o[i]} from pipe '$a $b' failed -- expected '${e[i]}', got '$g'"
3987c2fbfb3SApril Chin		done
3997c2fbfb3SApril Chin	done
4007c2fbfb3SApril Chindone
4017c2fbfb3SApril Chin
4027c2fbfb3SApril Chinif	[[ $lc_utf8 ]]
4037c2fbfb3SApril Chinthen	export LC_ALL=en_US.UTF-8
4047c2fbfb3SApril Chin	typeset -a c=( '' 'A' $'\303\274' $'\342\202\254' )
4057c2fbfb3SApril Chin	integer i w
4067c2fbfb3SApril Chin	typeset o
4077c2fbfb3SApril Chin	if	(( ${#c[2]} == 1 && ${#c[3]} == 1 ))
4087c2fbfb3SApril Chin	then	for i in 1 2 3
4097c2fbfb3SApril Chin		do	for o in n N
4107c2fbfb3SApril Chin			do	for w in 1 2 3
4117c2fbfb3SApril Chin				do	print -nr "${c[w]}" | read -${o}${i} g
4127c2fbfb3SApril Chin					if	[[ $o == N ]] && (( i > 1 ))
4137c2fbfb3SApril Chin					then	e=''
4147c2fbfb3SApril Chin					else	e=${c[w]}
4157c2fbfb3SApril Chin					fi
4167c2fbfb3SApril Chin					[[ $g == "$e" ]] || err_exit "read -${o}${i} failed for '${c[w]}' -- expected '$e', got '$g'"
4177c2fbfb3SApril Chin				done
4187c2fbfb3SApril Chin			done
4197c2fbfb3SApril Chin		done
4207c2fbfb3SApril Chin	fi
4217c2fbfb3SApril Chinfi
4227c2fbfb3SApril Chin
42334f9b3eeSRoland Mainzexec 3<&2
42434f9b3eeSRoland Mainzfile=$tmp/file
42534f9b3eeSRoland Mainzredirect 5>$file 2>&5
42634f9b3eeSRoland Mainzprint -u5 -f 'This is a test\n'
42734f9b3eeSRoland Mainzprint -u2 OK
42834f9b3eeSRoland Mainzexec 2<&3
42934f9b3eeSRoland Mainzexp=$'This is a test\nOK'
43034f9b3eeSRoland Mainzgot=$(< $file)
43134f9b3eeSRoland Mainz[[ $got == $exp ]] || err_exit "output garbled when stderr is duped -- expected $(printf %q "$exp"), got $(printf %q "$got")"
43234f9b3eeSRoland Mainzprint 'hello world' > $file
43334f9b3eeSRoland Mainz1<>; $file  1># ((5))
43434f9b3eeSRoland Mainz(( $(wc -c < $file) == 5 )) || err_exit "$file was not truncate to 5 bytes"
43534f9b3eeSRoland Mainz
43634f9b3eeSRoland Mainz$SHELL -c "PS4=':2:'
43734f9b3eeSRoland Mainz	exec 1> $tmp/21.out 2> $tmp/22.out
43834f9b3eeSRoland Mainz	set -x
43934f9b3eeSRoland Mainz	printf ':1:A:'
44034f9b3eeSRoland Mainz	print \$(:)
44134f9b3eeSRoland Mainz	print :1:Z:" 1> $tmp/11.out 2> $tmp/12.out
44234f9b3eeSRoland Mainz[[ -s $tmp/11.out ]] && err_exit "standard output leaked past redirection"
44334f9b3eeSRoland Mainz[[ -s $tmp/12.out ]] && err_exit "standard error leaked past redirection"
44434f9b3eeSRoland Mainzexp=$':1:A:\n:1:Z:'
44534f9b3eeSRoland Mainzgot=$(<$tmp/21.out)
44634f9b3eeSRoland Mainz[[ $exp == "$got" ]] || err_exit "standard output garbled -- expected $(printf %q "$exp"), got $(printf %q "$got")"
44734f9b3eeSRoland Mainzexp=$':2:printf :1:A:\n:2::\n:2:print\n:2:print :1:Z:'
44834f9b3eeSRoland Mainzgot=$(<$tmp/22.out)
44934f9b3eeSRoland Mainz[[ $exp == "$got" ]] || err_exit "standard error garbled -- expected $(printf %q "$exp"), got $(printf %q "$got")"
45034f9b3eeSRoland Mainz
451da2e3ebdSchinexit $((Errors))
452