Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/ksh93/tests/basic.sh
1810 views
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 <[email protected]> #
18
# #
19
########################################################################
20
function err_exit
21
{
22
print -u2 -n "\t"
23
print -u2 -r ${Command}[$1]: "${@:2}"
24
let Errors+=1
25
}
26
alias err_exit='err_exit $LINENO'
27
28
Command=${0##*/}
29
integer Errors=0
30
31
tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
32
trap "cd /; rm -rf $tmp" EXIT
33
34
# test basic file operations like redirection, pipes, file expansion
35
set -- \
36
go+r 0000 \
37
go-r 0044 \
38
ug=r 0330 \
39
go+w 0000 \
40
go-w 0022 \
41
ug=w 0550 \
42
go+x 0000 \
43
go-x 0011 \
44
ug=x 0660 \
45
go-rx 0055 \
46
uo-wx 0303 \
47
ug-rw 0660 \
48
o= 0007
49
while (( $# >= 2 ))
50
do umask 0
51
umask $1
52
g=$(umask)
53
[[ $g == $2 ]] || err_exit "umask 0; umask $1 failed -- expected $2, got $g"
54
shift 2
55
done
56
umask u=rwx,go=rx || err_exit "umask u=rws,go=rx failed"
57
if [[ $(umask -S) != u=rwx,g=rx,o=rx ]]
58
then err_exit 'umask -S incorrect'
59
fi
60
pwd=$PWD
61
[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL
62
cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
63
um=$(umask -S)
64
( umask 0777; > foobar )
65
rm -f foobar
66
> foobar
67
[[ -r foobar ]] || err_exit 'umask not being restored after subshell'
68
umask "$um"
69
rm -f foobar
70
# optimizer bug test
71
> foobar
72
for i in 1 2
73
do print foobar*
74
rm -f foobar
75
done > out
76
if [[ "$(<out)" != "foobar"$'\n'"foobar*" ]]
77
then print -u2 "optimizer bug with file expansion"
78
fi
79
rm -f out foobar
80
mkdir dir
81
if [[ $(print */) != dir/ ]]
82
then err_exit 'file expansion with trailing / not working'
83
fi
84
if [[ $(print *) != dir ]]
85
then err_exit 'file expansion with single file not working'
86
fi
87
print hi > .foo
88
if [[ $(print *) != dir ]]
89
then err_exit 'file expansion leading . not working'
90
fi
91
date > dat1 || err_exit "date > dat1 failed"
92
test -r dat1 || err_exit "dat1 is not readable"
93
x=dat1
94
cat <$x > dat2 || err_exit "cat < $x > dat2 failed"
95
cat dat1 dat2 | cat | cat | cat > dat3 || err_exit "cat pipe failed"
96
cat > dat4 <<!
97
$(date)
98
!
99
cat dat1 dat2 | cat | cat | cat > dat5 &
100
wait $!
101
set -- dat*
102
if (( $# != 5 ))
103
then err_exit "dat* matches only $# files"
104
fi
105
if (command > foo\\abc) 2> /dev/null
106
then set -- foo*
107
if [[ $1 != 'foo\abc' ]]
108
then err_exit 'foo* does not match foo\abc'
109
fi
110
fi
111
if ( : > TT* && : > TTfoo ) 2>/dev/null
112
then set -- TT*
113
if (( $# < 2 ))
114
then err_exit 'TT* not expanding when file TT* exists'
115
fi
116
fi
117
cd ~- || err_exit "cd back failed"
118
cat > $tmp/script <<- !
119
#! $SHELL
120
print -r -- \$0
121
!
122
chmod 755 $tmp/script
123
if [[ $($tmp/script) != "$tmp/script" ]]
124
then err_exit '$0 not correct for #! script'
125
fi
126
bar=foo
127
eval foo=\$bar
128
if [[ $foo != foo ]]
129
then err_exit 'eval foo=\$bar not working'
130
fi
131
bar='foo=foo\ bar'
132
eval $bar
133
if [[ $foo != 'foo bar' ]]
134
then err_exit 'eval foo=\$bar, with bar="foo\ bar" not working'
135
fi
136
cd /tmp
137
cd ../../tmp || err_exit "cd ../../tmp failed"
138
if [[ $PWD != /tmp ]]
139
then err_exit 'cd ../../tmp is not /tmp'
140
fi
141
( sleep 2; cat <<!
142
foobar
143
!
144
) | cat > $tmp/foobar &
145
wait $!
146
foobar=$( < $tmp/foobar)
147
if [[ $foobar != foobar ]]
148
then err_exit "$foobar is not foobar"
149
fi
150
{
151
print foo
152
/bin/echo bar
153
print bam
154
} > $tmp/foobar
155
if [[ $( < $tmp/foobar) != $'foo\nbar\nbam' ]]
156
then err_exit "output file pointer not shared correctly"
157
fi
158
cat > $tmp/foobar <<\!
159
print foo
160
/bin/echo bar
161
print bam
162
!
163
chmod +x $tmp/foobar
164
if [[ $($tmp/foobar) != $'foo\nbar\nbam' ]]
165
then err_exit "script not working"
166
fi
167
if [[ $($tmp/foobar | /bin/cat) != $'foo\nbar\nbam' ]]
168
then err_exit "script | cat not working"
169
fi
170
if [[ $( $tmp/foobar) != $'foo\nbar\nbam' ]]
171
then err_exit "output file pointer not shared correctly"
172
fi
173
rm -f $tmp/foobar
174
x=$( (print foo) ; (print bar) )
175
if [[ $x != $'foo\nbar' ]]
176
then err_exit " ( (print foo);(print bar ) failed"
177
fi
178
x=$( (/bin/echo foo) ; (print bar) )
179
if [[ $x != $'foo\nbar' ]]
180
then err_exit " ( (/bin/echo);(print bar ) failed"
181
fi
182
x=$( (/bin/echo foo) ; (/bin/echo bar) )
183
if [[ $x != $'foo\nbar' ]]
184
then err_exit " ( (/bin/echo);(/bin/echo bar ) failed"
185
fi
186
cat > $tmp/script <<\!
187
if [[ -p /dev/fd/0 ]]
188
then builtin cat
189
cat - > /dev/null
190
[[ -p /dev/fd/0 ]] && print ok
191
else print no
192
fi
193
!
194
chmod +x $tmp/script
195
case $( (print) | $tmp/script;:) in
196
ok) ;;
197
no) err_exit "[[ -p /dev/fd/0 ]] fails for standard input pipe" ;;
198
*) err_exit "builtin replaces standard input pipe" ;;
199
esac
200
print 'print $0' > $tmp/script
201
print ". $tmp/script" > $tmp/scriptx
202
chmod +x $tmp/scriptx
203
if [[ $($tmp/scriptx) != $tmp/scriptx ]]
204
then err_exit '$0 not correct for . script'
205
fi
206
cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
207
print ./b > ./a; print ./c > b; print ./d > c; print ./e > d; print "echo \"hello there\"" > e
208
chmod 755 a b c d e
209
x=$(./a)
210
if [[ $x != "hello there" ]]
211
then err_exit "nested scripts failed"
212
fi
213
x=$( (./a) | cat)
214
if [[ $x != "hello there" ]]
215
then err_exit "scripts in subshells fail"
216
fi
217
cd ~- || err_exit "cd back failed"
218
x=$( (/bin/echo foo) 2> /dev/null )
219
if [[ $x != foo ]]
220
then err_exit "subshell in command substitution fails"
221
fi
222
exec 9>& 1
223
exec 1>&-
224
x=$(print hello)
225
if [[ $x != hello ]]
226
then err_exit "command subsitution with stdout closed failed"
227
fi
228
exec >& 9
229
cd $pwd
230
x=$(cat <<\! | $SHELL
231
/bin/echo | /bin/cat
232
/bin/echo hello
233
!
234
)
235
if [[ $x != $'\n'hello ]]
236
then err_exit "$SHELL not working when standard input is a pipe"
237
fi
238
x=$( (/bin/echo hello) 2> /dev/null )
239
if [[ $x != hello ]]
240
then err_exit "subshell in command substitution with 1 closed fails"
241
fi
242
cat > $tmp/script <<- \!
243
read line 2> /dev/null
244
print done
245
!
246
if [[ $($SHELL $tmp/script <&-) != done ]]
247
then err_exit "executing script with 0 closed fails"
248
fi
249
trap '' INT
250
cat > $tmp/script <<- \!
251
trap 'print bad' INT
252
kill -s INT $$
253
print good
254
!
255
chmod +x $tmp/script
256
if [[ $($SHELL $tmp/script) != good ]]
257
then err_exit "traps ignored by parent not ignored"
258
fi
259
trap - INT
260
cat > $tmp/script <<- \!
261
read line
262
/bin/cat
263
!
264
if [[ $($SHELL $tmp/script <<!
265
one
266
two
267
!
268
) != two ]]
269
then err_exit "standard input not positioned correctly"
270
fi
271
word=$(print $'foo\nbar' | { read line; /bin/cat;})
272
if [[ $word != bar ]]
273
then err_exit "pipe to { read line; /bin/cat;} not working"
274
fi
275
word=$(print $'foo\nbar' | ( read line; /bin/cat) )
276
if [[ $word != bar ]]
277
then err_exit "pipe to ( read line; /bin/cat) not working"
278
fi
279
if [[ $(print x{a,b}y) != 'xay xby' ]]
280
then err_exit 'brace expansion not working'
281
fi
282
if [[ $(for i in foo bar
283
do ( tgz=$(print $i)
284
print $tgz)
285
done) != $'foo\nbar' ]]
286
then err_exit 'for loop subshell optimizer bug'
287
fi
288
unset a1
289
optbug()
290
{
291
set -A a1 foo bar bam
292
integer i
293
for ((i=0; i < 3; i++))
294
do
295
(( ${#a1[@]} < 2 )) && return 0
296
set -- "${a1[@]}"
297
shift
298
set -A a1 -- "$@"
299
done
300
return 1
301
}
302
optbug || err_exit 'array size optimzation bug'
303
wait # not running --pipefail which would interfere with subsequent tests
304
: $(jobs -p) # required to clear jobs for next jobs -p (interactive side effect)
305
sleep 20 &
306
pids=$!
307
if [[ $(jobs -p) != $! ]]
308
then err_exit 'jobs -p not reporting a background job'
309
fi
310
sleep 20 &
311
pids="$pids $!"
312
foo()
313
{
314
set -- $(jobs -p)
315
(( $# == 2 )) || err_exit "$# jobs not reported -- 2 expected"
316
}
317
foo
318
kill $pids
319
320
[[ $( (trap 'print alarm' ALRM; sleep 4) & sleep 2; kill -ALRM $!; sleep 2; wait) == alarm ]] || err_exit 'ALRM signal not working'
321
[[ $($SHELL -c 'trap "" HUP; $SHELL -c "(sleep 2;kill -HUP $$)& sleep 4;print done"') != done ]] && err_exit 'ignored traps not being ignored'
322
[[ $($SHELL -c 'o=foobar; for x in foo bar; do (o=save);print $o;done' 2> /dev/null ) == $'foobar\nfoobar' ]] || err_exit 'for loop optimization subshell bug'
323
command exec 3<> /dev/null
324
if cat /dev/fd/3 >/dev/null 2>&1 || whence mkfifo > /dev/null
325
then [[ $($SHELL -c 'cat <(print foo)' 2> /dev/null) == foo ]] || err_exit 'process substitution not working'
326
[[ $($SHELL -c $'tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!!
327
line0
328
line1
329
line2
330
!!!
331
wait
332
cat '$tmp/scriptx 2> /dev/null) == line1 ]] || err_exit '>() process substitution fails'
333
> $tmp/scriptx
334
[[ $($SHELL -c $'
335
for i in 1
336
do tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!!
337
line0
338
line1
339
line2
340
!!!
341
done
342
wait
343
cat '$tmp/scriptx 2>> /dev/null) == line1 ]] || err_exit '>() process substitution fails in for loop'
344
[[ $({ $SHELL -c 'cat <(for i in x y z; do print $i; done)';} 2> /dev/null) == $'x\ny\nz' ]] ||
345
err_exit 'process substitution of compound commands not working'
346
fi
347
[[ $($SHELL -r 'command -p :' 2>&1) == *restricted* ]] || err_exit 'command -p not restricted'
348
print cat > $tmp/scriptx
349
chmod +x $tmp/scriptx
350
[[ $($SHELL -c "print foo | $tmp/scriptx ;:" 2> /dev/null ) == foo ]] || err_exit 'piping into script fails'
351
[[ $($SHELL -c 'X=1;print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 1 ]] || err_exit 'x=1;${x:=$(..."...")} failure'
352
[[ $($SHELL -c 'print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 0 ]] || err_exit '${x:=$(..."...")} failure'
353
if cat /dev/fd/3 >/dev/null 2>&1 || whence mkfifo > /dev/null
354
then [[ $(cat <(print hello) ) == hello ]] || err_exit "process substitution not working outside for or while loop"
355
$SHELL -c '[[ $(for i in 1;do cat <(print hello);done ) == hello ]]' 2> /dev/null|| err_exit "process substitution not working in for or while loop"
356
fi
357
exec 3> /dev/null
358
print 'print foo "$@"' > $tmp/scriptx
359
[[ $( print "($tmp/scriptx bar)" | $SHELL 2>/dev/null) == 'foo bar' ]] || err_exit 'script pipe to shell fails'
360
print "#! $SHELL" > $tmp/scriptx
361
print 'print -- $0' >> $tmp/scriptx
362
chmod +x $tmp/scriptx
363
[[ $($tmp/scriptx) == $tmp/scriptx ]] || err_exit "\$0 is $0 instead of $tmp/scriptx"
364
cat > $tmp/scriptx <<- \EOF
365
myfilter() { x=$(print ok | cat); print -r -- $SECONDS;}
366
set -o pipefail
367
sleep 3 | myfilter
368
EOF
369
(( $($SHELL $tmp/scriptx) > 2.0 )) && err_exit 'command substitution causes pipefail option to hang'
370
exec 3<&-
371
( typeset -r foo=bar) 2> /dev/null || err_exit 'readonly variables set in a subshell cannot unset'
372
$SHELL -c 'x=${ print hello;}; [[ $x == hello ]]' 2> /dev/null || err_exit '${ command;} not supported'
373
$SHELL 2> /dev/null <<- \EOF || err_exit 'multiline ${...} command substitution not supported'
374
x=${
375
print hello
376
}
377
[[ $x == hello ]]
378
EOF
379
$SHELL 2> /dev/null <<- \EOF || err_exit '${...} command substitution with side effects not supported '
380
y=bye
381
x=${
382
y=hello
383
print hello
384
}
385
[[ $y == $x ]]
386
EOF
387
$SHELL 2> /dev/null <<- \EOF || err_exit 'nested ${...} command substitution not supported'
388
x=${
389
print ${ print hello;} $(print world)
390
}
391
[[ $x == 'hello world' ]]
392
EOF
393
$SHELL 2> /dev/null <<- \EOF || err_exit 'terminating } is not a reserved word with ${ command }'
394
x=${ { print -n } ; print -n hello ; } ; print ' world' }
395
[[ $x == '}hello world' ]]
396
EOF
397
$SHELL 2> /dev/null <<- \EOF || err_exit '${ command;}xxx not working'
398
f()
399
{
400
print foo
401
}
402
[[ ${ f;}bar == foobar ]]
403
EOF
404
405
unset foo
406
[[ ! ${foo[@]} ]] || err_exit '${foo[@]} is not empty when foo is unset'
407
[[ ! ${foo[3]} ]] || err_exit '${foo[3]} is not empty when foo is unset'
408
[[ $(print "[${ print foo }]") == '[foo]' ]] || err_exit '${...} not working when } is followed by ]'
409
[[ $(print "${ print "[${ print foo }]" }") == '[foo]' ]] || err_exit 'nested ${...} not working when } is followed by ]'
410
unset foo
411
foo=$(false) > /dev/null && err_exit 'failed command substitution with redirection not returning false'
412
expected=foreback
413
got=$(print -n fore; (sleep 2;print back)&)
414
[[ $got == $expected ]] || err_exit "command substitution background process output error -- got '$got', expected '$expected'"
415
416
binfalse=$(whence -p false)
417
for false in false $binfalse
418
do x=$($false) && err_exit "x=\$($false) should fail"
419
$($false) && err_exit "\$($false) should fail"
420
$($false) > /dev/null && err_exit "\$($false) > /dev/null should fail"
421
done
422
if env x-a=y >/dev/null 2>&1
423
then [[ $(env 'x-a=y' $SHELL -c 'env | grep x-a') == *x-a=y* ]] || err_exit 'invalid environment variables not preserved'
424
fi
425
float s=SECONDS
426
sleep=$(whence -p sleep)
427
for i in 1 2
428
do print $i
429
done | while read sec; do ( $sleep $sec; $sleep $sec) done
430
(( (SECONDS-s) < 4)) && err_exit '"command | while read...done" finishing too fast'
431
s=SECONDS
432
set -o pipefail
433
for ((i=0; i < 30; i++))
434
do print hello
435
sleep .1
436
done | $sleep 1
437
(( (SECONDS-s) < 2 )) || err_exit 'early termination not causing broken pipe'
438
[[ $({ trap 'print trap' 0; print -n | $(whence -p cat); } & wait $!) == trap ]] || err_exit 'trap on exit not getting triggered'
439
var=$({ trap 'print trap' ERR; print -n | $binfalse; } & wait $!)
440
[[ $var == trap ]] || err_exit 'trap on ERR not getting triggered'
441
442
exp=
443
got=$(
444
function fun
445
{
446
$binfalse && echo FAILED
447
}
448
: works if this line deleted : |
449
fun
450
: works if this line deleted :
451
)
452
[[ $got == $exp ]] || err_exit "pipe to function with conditional fails -- expected '$exp', got '$got'"
453
got=$(
454
: works if this line deleted : |
455
{ $binfalse && echo FAILED; }
456
: works if this line deleted :
457
)
458
[[ $got == $exp ]] || err_exit "pipe to { ... } with conditional fails -- expected '$exp', got '$got'"
459
460
got=$(
461
: works if this line deleted : |
462
( $binfalse && echo FAILED )
463
: works if this line deleted :
464
)
465
[[ $got == $exp ]] || err_exit "pipe to ( ... ) with conditional fails -- expected '$exp', got '$got'"
466
467
( $SHELL -c 'trap : DEBUG; x=( $foo); exit 0') 2> /dev/null || err_exit 'trap DEBUG fails'
468
469
bintrue=$(whence -p true)
470
set -o pipefail
471
float start=$SECONDS end
472
for ((i=0; i < 2; i++))
473
do print foo
474
sleep 1.5
475
done | { read; $bintrue; end=$SECONDS ;}
476
(( (SECONDS-start) < 1 )) && err_exit "pipefail not waiting for pipe to finish"
477
set +o pipefail
478
(( (SECONDS-end) > 2 )) && err_exit "pipefail causing $bintrue to wait for other end of pipe"
479
480
481
{ env A__z=C+SHLVL $SHELL -c : ;} 2> /dev/null || err_exit "SHLVL with wrong attribute fails"
482
483
if [[ $bintrue ]]
484
then float t0=SECONDS
485
{ time sleep 1.5 | $bintrue ;} 2> /dev/null
486
(( (SECONDS-t0) < 1 )) && err_exit 'time not waiting for pipeline to complete'
487
fi
488
489
cat > $tmp/foo.sh <<- \EOF
490
eval "cat > /dev/null < /dev/null"
491
sleep 1
492
EOF
493
float sec=SECONDS
494
. $tmp/foo.sh | cat > /dev/null
495
(( (SECONDS-sec) < .7 )) && err_exit '. script does not restore output redirection with eval'
496
497
file=$tmp/foobar
498
builtin cat
499
for ((n=0; n < 1000; n++))
500
do
501
> $file
502
{ sleep .001;echo $? >$file;} | cat > /dev/null
503
if [[ ! -s $file ]]
504
then err_exit 'output from pipe is lost with pipe to builtin'
505
break;
506
fi
507
done
508
509
$SHELL -c 'kill -0 123456789123456789123456789' 2> /dev/null && err_exit 'kill not catching process id overflows'
510
511
[[ $($SHELL -c '{ cd..; print ok;}' 2> /dev/null) == ok ]] || err_exit 'command name ending in .. causes shell to abort'
512
513
$SHELL -xc '$(LD_LIBRARY_PATH=$LD_LIBRARY_PATH exec $SHELL -c :)' > /dev/null 2>&1 || err_exit "ksh -xc '(name=value exec ksh)' fails with err=$?"
514
515
$SHELL 2> /dev/null -c $'for i;\ndo :;done' || err_exit 'for i ; <newline> not vaid'
516
517
exit $((Errors<125?Errors:125))
518
519