1########################################################################
2#                                                                      #
3#               This software is part of the ast package               #
4#          Copyright (c) 1982-2012 AT&T Intellectual Property          #
5#                      and is licensed under the                       #
6#                 Eclipse Public License, Version 1.0                  #
7#                    by AT&T Intellectual Property                     #
8#                                                                      #
9#                A copy of the License is available at                 #
10#          http://www.eclipse.org/org/documents/epl-v10.html           #
11#         (with md5 checksum b35adb5213ca9657e911e9befb180842)         #
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
31tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
32trap "cd /; rm -rf $tmp" EXIT
33
34cd $tmp || exit
35type /xxxxxx > out1 2> out2
36[[ -s out1 ]] && err_exit 'type should not write on stdout for not found case'
37[[ -s out2 ]] || err_exit 'type should write on stderr for not found case'
38mkdir dir1 dir2
39cat  > dir1/foobar << '+++'
40foobar() { print foobar1;}
41function dir1 { print dir1;}
42+++
43cat  > dir2/foobar << '+++'
44foobar() { print foobar2;}
45function dir2 { print dir2;}
46+++
47chmod +x dir[12]/foobar
48p=$PATH
49FPATH=$PWD/dir1
50PATH=$FPATH:$p
51[[ $( foobar) == foobar1 ]] || err_exit 'foobar should output foobar1'
52FPATH=$PWD/dir2
53PATH=$FPATH:$p
54[[ $(foobar) == foobar2 ]] || err_exit 'foobar should output foobar2'
55FPATH=$PWD/dir1
56PATH=$FPATH:$p
57[[ $(foobar) == foobar1 ]] || err_exit 'foobar should output foobar1 again'
58FPATH=$PWD/dir2
59PATH=$FPATH:$p
60[[ ${ foobar;} == foobar2 ]] || err_exit 'foobar should output foobar2 with ${}'
61[[ ${ dir2;} == dir2 ]] || err_exit 'should be dir2'
62[[ ${ dir1;} == dir1 ]] 2> /dev/null &&  err_exit 'should not be be dir1'
63FPATH=$PWD/dir1
64PATH=$FPATH:$p
65[[ ${ foobar;} == foobar1 ]] || err_exit 'foobar should output foobar1 with ${}'
66[[ ${ dir1;} == dir1 ]] || err_exit 'should be dir1'
67[[ ${ dir2;} == dir2 ]] 2> /dev/null &&  err_exit 'should not be be dir2'
68FPATH=$PWD/dir2
69PATH=$FPATH:$p
70[[ ${ foobar;} == foobar2 ]] || err_exit 'foobar should output foobar2 with ${} again'
71PATH=$p
72(PATH="/bin")
73[[ $($SHELL -c 'print -r -- "$PATH"') == "$PATH" ]] || err_exit 'export PATH lost in subshell'
74cat > bug1 <<- EOF
75	print print ok > $tmp/ok
76	/bin/chmod 755 $tmp/ok
77	function a
78	{
79	        typeset -x PATH=$tmp
80	        ok
81	}
82	path=\$PATH
83	unset PATH
84	a
85	PATH=\$path
86}
87EOF
88[[ $($SHELL ./bug1 2>/dev/null) == ok ]]  || err_exit "PATH in function not working"
89cat > bug1 <<- \EOF
90	function lock_unlock
91	{
92	typeset PATH=/usr/bin
93	typeset -x PATH=''
94	}
95
96	PATH=/usr/bin
97	: $(PATH=/usr/bin getconf PATH)
98	typeset -ft lock_unlock
99	lock_unlock
100EOF
101($SHELL ./bug1)  2> /dev/null || err_exit "path_delete bug"
102mkdir tdir
103if	$SHELL tdir > /dev/null 2>&1
104then	err_exit 'not an error to run ksh on a directory'
105fi
106
107print 'print hi' > ls
108if	[[ $($SHELL ls 2> /dev/null) != hi ]]
109then	err_exit "$SHELL name not executing version in current directory"
110fi
111if	[[ $(ls -d . 2>/dev/null) == . && $(PATH=/bin:/usr/bin:$PATH ls -d . 2>/dev/null) != . ]]
112then	err_exit 'PATH export in command substitution not working'
113fi
114pwd=$PWD
115# get rid of leading and trailing : and trailing :.
116PATH=${PATH%.}
117PATH=${PATH%:}
118PATH=${PATH#.}
119PATH=${PATH#:}
120path=$PATH
121var=$(whence date)
122dir=$(basename "$var")
123for i in 1 2 3 4 5 6 7 8 9 0
124do	if	! whence notfound$i 2> /dev/null
125	then	cmd=notfound$i
126		break
127	fi
128done
129print 'print hello' > date
130chmod +x date
131print 'print notfound' >  $cmd
132chmod +x "$cmd"
133> foo
134chmod 755 foo
135for PATH in $path :$path $path: .:$path $path: $path:. $PWD::$path $PWD:.:$path $path:$PWD $path:.:$PWD
136do
137#	print path=$PATH $(whence date)
138#	print path=$PATH $(whence "$cmd")
139		date
140		"$cmd"
141done > /dev/null 2>&1
142builtin -d date 2> /dev/null
143if	[[ $(PATH=:/usr/bin; date) != 'hello' ]]
144then	err_exit "leading : in path not working"
145fi
146(
147	PATH=$PWD:
148	builtin chmod
149	print 'print cannot execute' > noexec
150	chmod 644 noexec
151	if	[[ ! -x noexec ]]
152	then	noexec > /dev/null 2>&1
153	else	exit 126
154	fi
155)
156status=$?
157[[ $status == 126 ]] || err_exit "exit status of non-executable is $status -- 126 expected"
158builtin -d rm 2> /dev/null
159chmod=$(whence chmod)
160rm=$(whence rm)
161d=$(dirname "$rm")
162
163chmod=$(whence chmod)
164
165for cmd in date foo
166do	exp="$cmd found"
167	print print $exp > $cmd
168	$chmod +x $cmd
169	got=$($SHELL -c "unset FPATH; PATH=/dev/null; $cmd" 2>&1)
170	[[ $got == $exp ]] && err_exit "$cmd as last command should not find ./$cmd with PATH=/dev/null"
171	got=$($SHELL -c "unset FPATH; PATH=/dev/null; $cmd" 2>&1)
172	[[ $got == $exp ]] && err_exit "$cmd should not find ./$cmd with PATH=/dev/null"
173	exp=$PWD/./$cmd
174	got=$(unset FPATH; PATH=/dev/null; whence ./$cmd)
175	[[ $got == $exp ]] || err_exit "whence $cmd should find ./$cmd with PATH=/dev/null"
176	exp=$PWD/$cmd
177	got=$(unset FPATH; PATH=/dev/null; whence $PWD/$cmd)
178	[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd should find ./$cmd with PATH=/dev/null"
179done
180
181exp=''
182got=$($SHELL -c "unset FPATH; PATH=/dev/null; whence ./notfound" 2>&1)
183[[ $got == $exp ]] || err_exit "whence ./$cmd failed -- expected '$exp', got '$got'"
184got=$($SHELL -c "unset FPATH; PATH=/dev/null; whence $PWD/notfound" 2>&1)
185[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd failed -- expected '$exp', got '$got'"
186
187unset FPATH
188PATH=/dev/null
189for cmd in date foo
190do	exp="$cmd found"
191	print print $exp > $cmd
192	$chmod +x $cmd
193	got=$($cmd 2>&1)
194	[[ $got == $exp ]] && err_exit "$cmd as last command should not find ./$cmd with PATH=/dev/null"
195	got=$($cmd 2>&1; :)
196	[[ $got == $exp ]] && err_exit "$cmd should not find ./$cmd with PATH=/dev/null"
197	exp=$PWD/./$cmd
198	got=$(whence ./$cmd)
199	[[ $got == $exp ]] || err_exit "whence ./$cmd should find ./$cmd with PATH=/dev/null"
200	exp=$PWD/$cmd
201	got=$(whence $PWD/$cmd)
202	[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd should find ./$cmd with PATH=/dev/null"
203done
204exp=''
205got=$(whence ./notfound)
206[[ $got == $exp ]] || err_exit "whence ./$cmd failed -- expected '$exp', got '$got'"
207got=$(whence $PWD/notfound)
208[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd failed -- expected '$exp', got '$got'"
209
210PATH=$d:
211cp "$rm" kshrm
212if	[[ $(whence kshrm) != $PWD/kshrm  ]]
213then	err_exit 'trailing : in pathname not working'
214fi
215cp "$rm" rm
216PATH=:$d
217if	[[ $(whence rm) != $PWD/rm ]]
218then	err_exit 'leading : in pathname not working'
219fi
220PATH=$d: whence rm > /dev/null
221if	[[ $(whence rm) != $PWD/rm ]]
222then	err_exit 'pathname not restored after scoping'
223fi
224mkdir bin
225print 'print ok' > bin/tst
226chmod +x bin/tst
227if	[[ $(PATH=$PWD/bin tst 2>/dev/null) != ok ]]
228then	err_exit '(PATH=$PWD/bin foo) does not find $PWD/bin/foo'
229fi
230cd /
231if	whence ls > /dev/null
232then	PATH=
233	if	[[ $(whence rm) ]]
234	then	err_exit 'setting PATH to Null not working'
235	fi
236	unset PATH
237	if	[[ $(whence rm) != /*rm ]]
238	then	err_exit 'unsetting path  not working'
239	fi
240fi
241PATH=/dev:$tmp
242x=$(whence rm)
243typeset foo=$(PATH=/xyz:/abc :)
244y=$(whence rm)
245[[ $x != "$y" ]] && err_exit 'PATH not restored after command substitution'
246whence getconf > /dev/null  &&  err_exit 'getconf should not be found'
247builtin /bin/getconf
248PATH=/bin
249PATH=$(getconf PATH)
250x=$(whence ls)
251PATH=.:$PWD:${x%/ls}
252[[ $(whence ls) == "$x" ]] || err_exit 'PATH search bug when .:$PWD in path'
253PATH=$PWD:.:${x%/ls}
254[[ $(whence ls) == "$x" ]] || err_exit 'PATH search bug when :$PWD:. in path'
255cd   "${x%/ls}"
256[[ $(whence ls) == /* ]] || err_exit 'whence not generating absolute pathname'
257status=$($SHELL -c $'trap \'print $?\' EXIT;/xxx/a/b/c/d/e 2> /dev/null')
258[[ $status == 127 ]] || err_exit "not found command exit status $status -- expected 127"
259status=$($SHELL -c $'trap \'print $?\' EXIT;/dev/null 2> /dev/null')
260[[ $status == 126 ]] || err_exit "non executable command exit status $status -- expected 126"
261status=$($SHELL -c $'trap \'print $?\' ERR;/xxx/a/b/c/d/e 2> /dev/null')
262[[ $status == 127 ]] || err_exit "not found command with ERR trap exit status $status -- expected 127"
263status=$($SHELL -c $'trap \'print $?\' ERR;/dev/null 2> /dev/null')
264[[ $status == 126 ]] || err_exit "non executable command ERR trap exit status $status -- expected 126"
265
266# universe via PATH
267
268builtin getconf
269getconf UNIVERSE - att # override sticky default 'UNIVERSE = foo'
270
271[[ $(PATH=/usr/ucb/bin:/usr/bin echo -n ucb) == 'ucb' ]] || err_exit "ucb universe echo ignores -n option"
272[[ $(PATH=/usr/xpg/bin:/usr/bin echo -n att) == '-n att' ]] || err_exit "att universe echo does not ignore -n option"
273
274PATH=$path
275
276scr=$tmp/script
277exp=126
278
279: > $scr
280chmod a=x $scr
281{ got=$($scr; print $?); } 2>/dev/null
282[[ "$got" == "$exp" ]] || err_exit "unreadable empty script should fail -- expected $exp, got $got"
283{ got=$(command $scr; print $?); } 2>/dev/null
284[[ "$got" == "$exp" ]] || err_exit "command of unreadable empty script should fail -- expected $exp, got $got"
285[[ "$(:; $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "unreadable empty script in [[ ... ]] should fail -- expected $exp"
286[[ "$(:; command $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "command unreadable empty script in [[ ... ]] should fail -- expected $exp"
287got=$($SHELL -c "$scr; print \$?" 2>/dev/null)
288[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of unreadable empty script should fail -- expected $exp, got" $got
289got=$($SHELL -c "command $scr; print \$?" 2>/dev/null)
290[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of command of unreadable empty script should fail -- expected $exp, got" $got
291
292rm -f $scr
293print : > $scr
294chmod a=x $scr
295{ got=$($scr; print $?); } 2>/dev/null
296[[ "$got" == "$exp" ]] || err_exit "unreadable non-empty script should fail -- expected $exp, got $got"
297{ got=$(command $scr; print $?); } 2>/dev/null
298[[ "$got" == "$exp" ]] || err_exit "command of unreadable non-empty script should fail -- expected $exp, got $got"
299[[ "$(:; $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "unreadable non-empty script in [[ ... ]] should fail -- expected $exp"
300[[ "$(:; command $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "command unreadable non-empty script in [[ ... ]] should fail -- expected $exp"
301got=$($SHELL -c "$scr; print \$?" 2>/dev/null)
302[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of unreadable non-empty script should fail -- expected $exp, got" $got
303got=$($SHELL -c "command $scr; print \$?" 2>/dev/null)
304[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of command of unreadable non-empty script should fail -- expected $exp, got" $got
305
306# whence -a bug fix
307cd "$tmp"
308ifs=$IFS
309IFS=$'\n'
310PATH=$PATH:
311> ls
312chmod +x ls
313ok=
314for i in $(whence -a ls)
315do	if	[[ $i == *"$PWD/ls" ]]
316	then	ok=1
317		break;
318	fi
319done
320[[ $ok ]] || err_exit 'whence -a not finding all executables'
321rm -f ls
322PATH=${PATH%:}
323
324#whence -p bug fix
325function foo
326{
327	:
328}
329[[ $(whence -p foo) == foo ]] && err_exit 'whence -p foo should not find function foo'
330
331# whence -q bug fix
332$SHELL -c 'whence -q cat' & pid=$!
333sleep 3
334kill $! 2> /dev/null && err_exit 'whence -q appears to be hung'
335
336FPATH=$PWD
337print  'function foobar { :;}' > foobar
338autoload foobar;
339exec {m}< /dev/null
340for ((i=0; i < 25; i++))
341do	( foobar )
342done
343exec {m}<& -
344exec {n}< /dev/null
345(( n > m )) && err_exit 'autoload function in subshell leaves file open'
346
347# whence -a bug fix
348rmdir=rmdir
349if	mkdir "$rmdir"
350then	rm=${ whence rm;}
351	cp "$rm" "$rmdir"
352	{ PATH=:${rm%/rm} $SHELL -c "cd \"$rmdir\";whence -a rm";} > /dev/null 2>&1
353	exitval=$?
354	(( exitval==0 )) || err_exit "whence -a has exitval $exitval"
355fi
356
357[[ ! -d bin ]] && mkdir bin
358[[ ! -d fun ]] && mkdir fun
359print 'FPATH=../fun' > bin/.paths
360cat <<- \EOF > fun/myfun
361	function myfun
362	{
363		print myfun
364	}
365EOF
366x=$(FPATH= PATH=$PWD/bin $SHELL -c  ': $(whence less);myfun') 2> /dev/null
367[[ $x == myfun ]] || err_exit 'function myfun not found'
368
369cp $(whence -p echo) user_to_group_relationship.hdr.query
370FPATH=/foobar:
371PATH=$FPATH:$PATH:.
372[[ $(user_to_group_relationship.hdr.query foobar) == foobar ]] 2> /dev/null || err_exit 'Cannot execute command with . in name when PATH and FPATH end in :.'
373
374mkdir -p $tmp/new/bin
375mkdir $tmp/new/fun
376print FPATH=../fun > $tmp/new/bin/.paths
377print FPATH=../xxfun > $tmp/bin/.paths
378cp "$(whence -p echo)" $tmp/new/bin
379PATH=$tmp/bin:$tmp/new/bin:$PATH
380x=$(whence -p echo 2> /dev/null)
381[[ $x == "$tmp/new/bin/echo" ]] ||  err_exit 'nonexistant FPATH directory in .paths file causes path search to fail'
382
383$SHELL 2> /dev/null <<- \EOF || err_exit 'path search problem with non-existant directories in PATH'
384	PATH=/usr/nogood1/bin:/usr/nogood2/bin:/bin:/usr/bin
385	tail /dev/null && tail /dev/null
386EOF
387
388( PATH=/bin:usr/bin
389cat << END >/dev/null 2>&1
390${.sh.version}
391END
392) || err_exit '${.sh.xxx} variables causes cat not be found'
393
394exit $((Errors<125?Errors:125))
395
396