1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License (the "License").
6# You may not use this file except in compliance with the License.
7#
8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9# or http://www.opensolaris.org/os/licensing.
10# See the License for the specific language governing permissions
11# and limitations under the License.
12#
13# When distributing Covered Code, include this CDDL HEADER in each
14# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15# If applicable, add the following below this CDDL HEADER, with the
16# fields enclosed by brackets "[]" replaced with your own identifying
17# information: Portions Copyright [yyyy] [name of copyright owner]
18#
19# CDDL HEADER END
20#
21
22#
23# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24#
25
26#
27# This test checks whether the return code of a child process
28# is reported properly.
29#
30# This was reported as CR #6887363 ("Korn shell 93 sometimes
31# mishandles return value of its child process"):
32# ------------ snip ------------
33# Following construction sometimes ends with wrong return value.
34#
35#      56 	 echo $op | grep rand 2>&1 >/dev/null
36#      57 	 if [ $? = 0 ]; then
37#      58 		randseq="rand${SEED}"
38#      59 	 else
39#      60 		randseq="seq"
40#      61 	 fi
41#
42# Sometimes, the given result is "rand..." even when there is
43# no "rand" word in $op. This can be demonstrated with
44# TSufs/SnapShots/Func test case which excercises shown code
45# quite often.
46#
47# As it happens only sometimes, I suppose there is an
48# race-condition in handling return value from a child process.
49# ------------ snip ------------
50#
51
52# test setup
53function err_exit
54{
55	print -u2 -n "\t"
56	print -u2 -r ${Command}[$1]: "${@:2}"
57	(( Errors < 127 && Errors++ ))
58}
59alias err_exit='err_exit $LINENO'
60
61set -o nounset
62Command=${0##*/}
63integer Errors=0
64
65typeset ocwd
66typeset tmpdir
67typeset out
68
69# create temporary test directory
70ocwd="$PWD"
71tmpdir="$(mktemp -t -d "test_sun_solaris_cr_6887363_shell_sometimes_mishandles_return_value_of_its_child_process.XXXXXXXX")" || err_exit "Cannot create temporary directory"
72
73cd "${tmpdir}" || { err_exit "cd ${tmpdir} failed." ; exit $((Errors)) ; }
74
75
76# run tests
77
78# print test case from bug that ksh93 can read this script via stdin
79function cat_test
80{
81cat <<EOF
82#!/bin/sh
83#
84# Test derived from Sun's SnapShots Functional Suite
85#
86
87export PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin
88
89# WARNING: make sure "expr" and "grep" are _external_ commands in this test
90
91# start test
92_pcnt=0
93
94PASS(){
95	_pcnt=\`/usr/bin/expr \$_pcnt + 1\`
96	true
97}
98
99doblockstamper() {
100	output=\`/usr/bin/sleep .01\`
101	_status=\$?
102
103	PASS "Here I am"
104}
105
106lotsaFiles() {
107	OPS="read-seq read-rand syncread-seq syncread-seq"
108	echo \$OPS
109	for op in \$OPS; do
110	 echo \$op
111	 echo \$op | /usr/bin/grep rand 2>&1 >/dev/null
112	 status=\$?
113	 if [ \$status = 0 ]; then
114		randseq="rand"
115		phrase="read-rand"
116	 else
117		randseq="seq"
118		phrase="read-seq"
119	 fi
120	 retcode=\$status
121
122	 echo \$op | /usr/bin/grep sync 2>&1 >/dev/null
123	 status=\$?
124	 if [ \$status = 0 ]; then
125		syncasync="sync"
126		phrase="sync\$phrase"
127	 else
128		syncasync="async"
129	 fi
130	 retcode=\${status}-\${retcode}
131
132	if [ "\$op" != "\$phrase" ]; then
133		echo "Bad mode: \$op != \$phrase (\$retcode)"
134		exit 2
135	fi
136
137	 for sz in 1 2 3 4; do
138	   for type in 1 2 3 4; do
139		PASS "Something"
140		doblockstamper &
141	   done
142	   wait # Let a few finish
143	 done
144	done
145
146	wait    # Make sure everyone got done
147
148	PASS "lotsafiles \$1 \$fill"
149}
150
151cycle=0
152while [ cycle -lt 24 ]; do
153	cycle=\`/usr/bin/expr \$cycle + 1\`
154
155	lotsaFiles write
156	lotsaFiles write
157	lotsaFiles write
158
159	lotsaFiles read
160	lotsaFiles read
161	lotsaFiles read
162
163	PASS "Cycle"
164done
165exit 0
166EOF
167}
168
169# FIXME: we reset the VMALLOC_OPTIONS (and the depreciated VMDEBUG (for now)) variable for the run to avoid
170# that the test may run for hours. This may require re-investigation why this happens.
171out="$(unset VMALLOC_OPTIONS VMDEBUG ; cat_test | ${SHELL} 2>&1)" || err_exit "Unexpected exit code $?"
172[[ "${out}" != "" ]] || err_exit "No output from test"
173
174# filter output and check it
175out2="$(/usr/bin/egrep -v '^((read-seq|read-rand|syncread-seq|syncread-seq)[[:space:][:blank:]]*)*$' <<<"${out}")"
176[[ "${out2}" == "" ]] || err_exit "Unexpected output '${out2}'"
177
178
179cd "${ocwd}"
180rmdir "${tmpdir}" || err_exit "Cannot remove temporary directory ${tmpdir}".
181
182# tests done
183exit $((Errors))
184