1########################################################################
2#                                                                      #
3#               This software is part of the ast package               #
4#          Copyright (c) 1982-2010 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########################################################################
20# test the behavior of co-processes
21function err_exit
22{
23	print -u2 -n "\t"
24	print -u2 -r ${Command}[$1]: "${@:2}"
25	let Errors+=1
26}
27alias err_exit='err_exit $LINENO'
28
29Command=${0##*/}
30integer Errors=0
31
32tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
33trap "cd /; rm -rf $tmp" EXIT
34
35if	[[ -d /cygdrive ]]
36then	err_exit cygwin detected - coprocess tests disabled - enable at the risk of wedging your system
37	exit $((Errors))
38fi
39
40function ping # id
41{
42	integer x=0
43	while ((x++ < 5))
44	do	read -r
45		print -r "$1 $REPLY"
46	done
47}
48
49cat |&
50print -p "hello"
51read -p line
52[[ $line == hello ]] || err_exit 'coprocessing fails'
53exec 5>&p 6<&p
54print -u5 'hello again' || err_exit 'write on u5 fails'
55read -u6 line
56[[ $line == 'hello again' ]] || err_exit 'coprocess after moving fds fails'
57exec 5<&- 6<&-
58wait $!
59
60ping three |&
61exec 3>&p
62ping four |&
63exec 4>&p
64ping pipe |&
65
66integer count
67for i in three four pipe four pipe four three pipe pipe three pipe
68do	case $i in
69	three)	to=-u3;;
70	four)	to=-u4;;
71	pipe)	to=-p;;
72	esac
73	(( count++ ))
74	print $to $i $count
75done
76
77while	((count > 0))
78do	(( count-- ))
79	read -p
80	set -- $REPLY
81	if	[[ $1 != $2 ]]
82	then	err_exit "$1 does not match $2"
83	fi
84	case $1 in
85	three)	;;
86	four)	;;
87	pipe)	;;
88	*)	err_exit "unknown message +|$REPLY|+" ;;
89	esac
90done
91kill $(jobs -p) 2>/dev/null
92
93file=$tmp/regress
94cat > $file  <<\!
95/bin/cat |&
96!
97chmod +x $file
98sleep 10 |&
99$file 2> /dev/null || err_exit "parent coprocess prevents script coprocess"
100exec 5<&p 6>&p
101exec 5<&- 6>&-
102kill $(jobs -p) 2>/dev/null
103
104${SHELL-ksh} |&
105cop=$!
106exp=Done
107print -p $'print hello | cat\nprint '$exp
108read -t 5 -p
109read -t 5 -p
110got=$REPLY
111if	[[ $got != $exp ]]
112then	err_exit "${SHELL-ksh} coprocess io failed -- got '$got', expected '$exp'"
113fi
114exec 5<&p 6>&p
115exec 5<&- 6>&-
116{ sleep 4; kill $cop; } 2>/dev/null &
117spy=$!
118if	wait $cop 2>/dev/null
119then	kill $spy 2>/dev/null
120else	err_exit "coprocess hung after 'exec 5<&p 6>&p; exec 5<&- 6>&-'"
121fi
122wait
123
124{
125echo line1 | grep 'line2'
126echo line2 | grep 'line1'
127} |&
128SECONDS=0 count=0
129while	read -p -t 10 line
130do	((count++))
131done
132if	(( SECONDS > 8 ))
133then	err_exit "read -p hanging (SECONDS=$SECONDS count=$count)"
134fi
135wait $!
136
137( sleep 3 |& sleep 1 && kill $!; sleep 1; sleep 3 |& sleep 1 && kill $! ) ||
138	err_exit "coprocess cleanup not working correctly"
139{ : |& } 2>/dev/null ||
140	err_exit "subshell coprocess lingers in parent"
141wait $!
142
143unset N r e
144integer N=5
145e=12345
146(
147	integer i
148	for ((i = 1; i <= N; i++))
149	do	print $i |&
150		read -p r
151		print -n $r
152		wait $!
153	done
154	print
155) 2>/dev/null | read -t 10 r
156[[ $r == $e ]] || err_exit "coprocess timing bug -- expected $e, got '$r'"
157r=
158(
159	integer i
160	for ((i = 1; i <= N; i++))
161	do	print $i |&
162		sleep 0.01
163		r=$r$(cat <&p)
164		wait $!
165	done
166	print $r
167) 2>/dev/null | read -t 10 r
168[[ $r == $e ]] || err_exit "coprocess command substitution bug -- expected $e, got '$r'"
169
170(
171	/bin/cat |&
172	sleep 0.01
173	exec 6>&p
174	print -u6 ok
175	exec 6>&-
176	sleep 1
177	kill $! 2> /dev/null
178) && err_exit 'coprocess with subshell would hang'
179for sig in IOT ABRT
180do	if	( trap - $sig ) 2> /dev/null
181	then	if	[[ $( { sig=$sig $SHELL  2> /dev/null <<- '++EOF++'
182				cat |&
183				pid=$!
184				trap "print TRAP" $sig
185				(
186					sleep 2
187					kill -$sig $$
188					sleep 2
189					kill -$sig $$
190					kill $pid
191					sleep 2
192					kill $$
193				) &
194				read -p
195			++EOF++
196			} ) != $'TRAP\nTRAP' ]] 2> /dev/null
197		then	err_exit 'traps when reading from coprocess not working'
198		fi
199		break
200	fi
201done
202
203trap 'sleep_pid=; kill $pid; err_exit "coprocess 1 hung"' TERM
204{ sleep 5; kill $$; } &
205sleep_pid=$!
206builtin cat
207cat |&
208pid=$!
209exec 5<&p 6>&p
210print -u6 hi; read -u5
211[[ $REPLY == hi ]] || err_exit 'REPLY is $REPLY not hi'
212exec 6>&-
213wait $pid
214trap - TERM
215[[ $sleep_pid ]] && kill $sleep_pid
216
217trap 'sleep_pid=; kill $pid; err_exit "coprocess 2 hung"' TERM
218{ sleep 5; kill $$; } &
219sleep_pid=$!
220cat |&
221pid=$!
222print foo >&p 2> /dev/null || err_exit 'first write of foo to coprocess failed'
223print foo >&p 2> /dev/null || err_exit 'second write of foo to coprocess failed'
224kill $pid
225wait $pid 2> /dev/null
226trap - TERM
227[[ $sleep_pid ]] && kill $sleep_pid
228
229trap 'sleep_pid=; kill $pid; err_exit "coprocess 3 hung"' TERM
230{ sleep 5; kill $$; } &
231sleep_pid=$!
232cat |&
233pid=$!
234print -p foo
235print -p bar
236read <&p || err_exit 'first read from coprocess failed'
237[[ $REPLY == foo ]] || err_exit "first REPLY is $REPLY not foo"
238read <&p || err_exit 'second read from coprocess failed'
239[[ $REPLY == bar ]] || err_exit "second REPLY is $REPLY not bar"
240kill $pid
241wait $pid 2> /dev/null
242trap - TERM
243[[ $sleep_pid ]] && kill $sleep_pid
244
245exp=ksh
246got=$(print -r $'#00315
247COATTRIBUTES=\'label=make \'
248# @(#)$Id: libcoshell (AT&T Research) 2008-04-28 $
249_COSHELL_msgfd=5
250{ { (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)
251[[ $got == $exp ]] || err_exit "coshell(3) identification sequence failed -- expected '$exp', got '$got'"
252
253function cop
254{
255	read
256	print ok
257}
258
259exp=ok
260
261cop |&
262pid=$!
263if	print -p yo 2>/dev/null
264then	read -p got
265else	got='no coprocess'
266fi
267[[ $got == $exp ]] || err_exit "main coprocess main query failed -- expected $exp, got '$got'"
268kill $pid 2>/dev/null
269wait
270
271cop |&
272pid=$!
273(
274if	print -p yo 2>/dev/null
275then	read -p got
276else	got='no coprocess'
277fi
278[[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'"
279)
280kill $pid 2>/dev/null
281wait
282
283exp='no coprocess'
284
285(
286cop |&
287print $! > $tmp/pid
288)
289pid=$(<$tmp/pid)
290if	print -p yo 2>/dev/null
291then	read -p got
292else	got=$exp
293fi
294[[ $got == $exp ]] || err_exit "subshell coprocess main query failed -- expected $exp, got '$got'"
295kill $pid 2>/dev/null
296wait
297
298(
299cop |&
300print $! > $tmp/pid
301)
302pid=$(<$tmp/pid)
303(
304if	print -p yo 2>/dev/null
305then	read -p got
306else	got=$exp
307fi
308[[ $got == $exp ]] || err_exit "subshell coprocess subshell query failed -- expected $exp, got '$got'"
309kill $pid 2>/dev/null
310wait
311)
312
313exit $((Errors))
314