aboutsummaryrefslogtreecommitdiff
path: root/bin/sh/tests/execution
diff options
context:
space:
mode:
Diffstat (limited to 'bin/sh/tests/execution')
-rw-r--r--bin/sh/tests/execution/Makefile73
-rw-r--r--bin/sh/tests/execution/Makefile.depend10
-rw-r--r--bin/sh/tests/execution/bg1.02
-rw-r--r--bin/sh/tests/execution/bg10.03
-rw-r--r--bin/sh/tests/execution/bg10.0.stdout1
-rw-r--r--bin/sh/tests/execution/bg11.015
-rw-r--r--bin/sh/tests/execution/bg12.011
-rw-r--r--bin/sh/tests/execution/bg13.015
-rw-r--r--bin/sh/tests/execution/bg2.04
-rw-r--r--bin/sh/tests/execution/bg3.04
-rw-r--r--bin/sh/tests/execution/bg4.05
-rw-r--r--bin/sh/tests/execution/bg5.03
-rw-r--r--bin/sh/tests/execution/bg6.03
-rw-r--r--bin/sh/tests/execution/bg6.0.stdout1
-rw-r--r--bin/sh/tests/execution/bg7.04
-rw-r--r--bin/sh/tests/execution/bg8.04
-rw-r--r--bin/sh/tests/execution/bg9.04
-rw-r--r--bin/sh/tests/execution/env1.04
-rw-r--r--bin/sh/tests/execution/fork1.09
-rw-r--r--bin/sh/tests/execution/fork2.08
-rw-r--r--bin/sh/tests/execution/fork3.03
-rw-r--r--bin/sh/tests/execution/func1.03
-rw-r--r--bin/sh/tests/execution/func2.011
-rw-r--r--bin/sh/tests/execution/func3.06
-rw-r--r--bin/sh/tests/execution/hash1.011
-rw-r--r--bin/sh/tests/execution/int-cmd1.02
-rw-r--r--bin/sh/tests/execution/killed1.07
-rw-r--r--bin/sh/tests/execution/killed2.09
-rw-r--r--bin/sh/tests/execution/not1.03
-rw-r--r--bin/sh/tests/execution/not2.05
-rw-r--r--bin/sh/tests/execution/path1.014
-rw-r--r--bin/sh/tests/execution/pipefail1.03
-rw-r--r--bin/sh/tests/execution/pipefail2.423
-rw-r--r--bin/sh/tests/execution/pipefail3.423
-rw-r--r--bin/sh/tests/execution/pipefail4.423
-rw-r--r--bin/sh/tests/execution/pipefail5.424
-rw-r--r--bin/sh/tests/execution/pipefail6.425
-rw-r--r--bin/sh/tests/execution/pipefail7.04
-rw-r--r--bin/sh/tests/execution/redir1.026
-rw-r--r--bin/sh/tests/execution/redir2.028
-rw-r--r--bin/sh/tests/execution/redir3.02
-rw-r--r--bin/sh/tests/execution/redir4.03
-rw-r--r--bin/sh/tests/execution/redir5.02
-rw-r--r--bin/sh/tests/execution/redir6.020
-rw-r--r--bin/sh/tests/execution/redir7.020
-rw-r--r--bin/sh/tests/execution/set-C1.011
-rw-r--r--bin/sh/tests/execution/set-n1.06
-rw-r--r--bin/sh/tests/execution/set-n2.04
-rw-r--r--bin/sh/tests/execution/set-n3.03
-rw-r--r--bin/sh/tests/execution/set-n4.02
-rw-r--r--bin/sh/tests/execution/set-x1.07
-rw-r--r--bin/sh/tests/execution/set-x2.08
-rw-r--r--bin/sh/tests/execution/set-x3.08
-rw-r--r--bin/sh/tests/execution/set-x4.06
-rw-r--r--bin/sh/tests/execution/shellproc1.010
-rw-r--r--bin/sh/tests/execution/shellproc2.017
-rw-r--r--bin/sh/tests/execution/shellproc3.013
-rw-r--r--bin/sh/tests/execution/shellproc4.013
-rw-r--r--bin/sh/tests/execution/shellproc5.013
-rw-r--r--bin/sh/tests/execution/shellproc6.07
-rw-r--r--bin/sh/tests/execution/shellproc7.09
-rw-r--r--bin/sh/tests/execution/subshell1.05
-rw-r--r--bin/sh/tests/execution/subshell1.0.stdout2
-rw-r--r--bin/sh/tests/execution/subshell2.09
-rw-r--r--bin/sh/tests/execution/subshell3.03
-rw-r--r--bin/sh/tests/execution/subshell4.02
-rw-r--r--bin/sh/tests/execution/unknown1.028
-rw-r--r--bin/sh/tests/execution/unknown2.05
-rw-r--r--bin/sh/tests/execution/var-assign1.02
69 files changed, 576 insertions, 0 deletions
diff --git a/bin/sh/tests/execution/Makefile b/bin/sh/tests/execution/Makefile
new file mode 100644
index 000000000000..53cb97db9393
--- /dev/null
+++ b/bin/sh/tests/execution/Makefile
@@ -0,0 +1,73 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/bin/sh/${.CURDIR:T}
+
+.PATH: ${.CURDIR:H}
+ATF_TESTS_SH= functional_test
+
+${PACKAGE}FILES+= bg1.0
+${PACKAGE}FILES+= bg2.0
+${PACKAGE}FILES+= bg3.0
+${PACKAGE}FILES+= bg4.0
+${PACKAGE}FILES+= bg5.0
+${PACKAGE}FILES+= bg6.0 bg6.0.stdout
+${PACKAGE}FILES+= bg7.0
+${PACKAGE}FILES+= bg8.0
+${PACKAGE}FILES+= bg9.0
+${PACKAGE}FILES+= bg10.0 bg10.0.stdout
+${PACKAGE}FILES+= bg11.0
+${PACKAGE}FILES+= bg12.0
+${PACKAGE}FILES+= bg13.0
+${PACKAGE}FILES+= env1.0
+${PACKAGE}FILES+= fork1.0
+${PACKAGE}FILES+= fork2.0
+${PACKAGE}FILES+= fork3.0
+${PACKAGE}FILES+= func1.0
+${PACKAGE}FILES+= func2.0
+${PACKAGE}FILES+= func3.0
+${PACKAGE}FILES+= hash1.0
+${PACKAGE}FILES+= int-cmd1.0
+${PACKAGE}FILES+= killed1.0
+${PACKAGE}FILES+= killed2.0
+${PACKAGE}FILES+= not1.0
+${PACKAGE}FILES+= not2.0
+${PACKAGE}FILES+= path1.0
+${PACKAGE}FILES+= pipefail1.0
+${PACKAGE}FILES+= pipefail2.42
+${PACKAGE}FILES+= pipefail3.42
+${PACKAGE}FILES+= pipefail4.42
+${PACKAGE}FILES+= pipefail5.42
+${PACKAGE}FILES+= pipefail6.42
+${PACKAGE}FILES+= pipefail7.0
+${PACKAGE}FILES+= redir1.0
+${PACKAGE}FILES+= redir2.0
+${PACKAGE}FILES+= redir3.0
+${PACKAGE}FILES+= redir4.0
+${PACKAGE}FILES+= redir5.0
+${PACKAGE}FILES+= redir6.0
+${PACKAGE}FILES+= redir7.0
+${PACKAGE}FILES+= set-C1.0
+${PACKAGE}FILES+= set-n1.0
+${PACKAGE}FILES+= set-n2.0
+${PACKAGE}FILES+= set-n3.0
+${PACKAGE}FILES+= set-n4.0
+${PACKAGE}FILES+= set-x1.0
+${PACKAGE}FILES+= set-x2.0
+${PACKAGE}FILES+= set-x3.0
+${PACKAGE}FILES+= set-x4.0
+${PACKAGE}FILES+= shellproc1.0
+${PACKAGE}FILES+= shellproc2.0
+${PACKAGE}FILES+= shellproc3.0
+${PACKAGE}FILES+= shellproc4.0
+${PACKAGE}FILES+= shellproc5.0
+${PACKAGE}FILES+= shellproc6.0
+${PACKAGE}FILES+= shellproc7.0
+${PACKAGE}FILES+= subshell1.0 subshell1.0.stdout
+${PACKAGE}FILES+= subshell2.0
+${PACKAGE}FILES+= subshell3.0
+${PACKAGE}FILES+= subshell4.0
+${PACKAGE}FILES+= unknown1.0
+${PACKAGE}FILES+= unknown2.0
+${PACKAGE}FILES+= var-assign1.0
+
+.include <bsd.test.mk>
diff --git a/bin/sh/tests/execution/Makefile.depend b/bin/sh/tests/execution/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/bin/sh/tests/execution/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/bin/sh/tests/execution/bg1.0 b/bin/sh/tests/execution/bg1.0
new file mode 100644
index 000000000000..eae1e2a6eece
--- /dev/null
+++ b/bin/sh/tests/execution/bg1.0
@@ -0,0 +1,2 @@
+
+: `false` &
diff --git a/bin/sh/tests/execution/bg10.0 b/bin/sh/tests/execution/bg10.0
new file mode 100644
index 000000000000..3e825d9eda20
--- /dev/null
+++ b/bin/sh/tests/execution/bg10.0
@@ -0,0 +1,3 @@
+# The redirection overrides the </dev/null implicit in a background command.
+
+echo yes | ${SH} -c '{ cat & wait; } <&0'
diff --git a/bin/sh/tests/execution/bg10.0.stdout b/bin/sh/tests/execution/bg10.0.stdout
new file mode 100644
index 000000000000..7cfab5b05d62
--- /dev/null
+++ b/bin/sh/tests/execution/bg10.0.stdout
@@ -0,0 +1 @@
+yes
diff --git a/bin/sh/tests/execution/bg11.0 b/bin/sh/tests/execution/bg11.0
new file mode 100644
index 000000000000..380d2180fe79
--- /dev/null
+++ b/bin/sh/tests/execution/bg11.0
@@ -0,0 +1,15 @@
+
+T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXXXX`
+trap 'rm -rf $T' 0
+cd $T || exit 3
+mkfifo fifo1
+# Use a trap, not the default action, since the shell may catch SIGINT and
+# therefore its processing may be delayed.
+{ trap 'exit 5' TERM; read dummy <fifo1; exit 4; } &
+exec 3>fifo1
+kill -INT "$!"
+kill -TERM "$!"
+exec 3>&-
+wait "$!"
+r=$?
+[ "$r" = 5 ]
diff --git a/bin/sh/tests/execution/bg12.0 b/bin/sh/tests/execution/bg12.0
new file mode 100644
index 000000000000..ed1e0065b226
--- /dev/null
+++ b/bin/sh/tests/execution/bg12.0
@@ -0,0 +1,11 @@
+
+T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXXXX`
+trap 'rm -rf $T' 0
+cd $T || exit 3
+mkfifo fifo1
+{ trap - INT; : >fifo1; sleep 5 & wait; exit 4; } &
+: <fifo1
+kill -INT "$!"
+wait "$!"
+r=$?
+[ "$r" -gt 128 ] && [ "$(kill -l "$r")" = INT ]
diff --git a/bin/sh/tests/execution/bg13.0 b/bin/sh/tests/execution/bg13.0
new file mode 100644
index 000000000000..7f6fb87af665
--- /dev/null
+++ b/bin/sh/tests/execution/bg13.0
@@ -0,0 +1,15 @@
+
+T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXXXX`
+trap 'rm -rf $T' 0
+cd $T || exit 3
+mkfifo fifo1
+# Use a trap, not the default action, since the shell may catch SIGINT and
+# therefore its processing may be delayed.
+{ set -C; trap 'exit 5' TERM; read dummy <fifo1; exit 4; } &
+exec 3>fifo1
+kill -INT "$!"
+kill -TERM "$!"
+exec 3>&-
+wait "$!"
+r=$?
+[ "$r" = 5 ]
diff --git a/bin/sh/tests/execution/bg2.0 b/bin/sh/tests/execution/bg2.0
new file mode 100644
index 000000000000..29bdffb0b105
--- /dev/null
+++ b/bin/sh/tests/execution/bg2.0
@@ -0,0 +1,4 @@
+
+f() { return 42; }
+f
+: | : &
diff --git a/bin/sh/tests/execution/bg3.0 b/bin/sh/tests/execution/bg3.0
new file mode 100644
index 000000000000..0a411f611e1f
--- /dev/null
+++ b/bin/sh/tests/execution/bg3.0
@@ -0,0 +1,4 @@
+
+f() { return 42; }
+f
+(:) &
diff --git a/bin/sh/tests/execution/bg4.0 b/bin/sh/tests/execution/bg4.0
new file mode 100644
index 000000000000..4d63fa8b455f
--- /dev/null
+++ b/bin/sh/tests/execution/bg4.0
@@ -0,0 +1,5 @@
+
+x=''
+: ${x:=1} &
+wait
+exit ${x:-0}
diff --git a/bin/sh/tests/execution/bg5.0 b/bin/sh/tests/execution/bg5.0
new file mode 100644
index 000000000000..94c45dba370b
--- /dev/null
+++ b/bin/sh/tests/execution/bg5.0
@@ -0,0 +1,3 @@
+# A background command has an implicit </dev/null redirection.
+
+echo bad | ${SH} -c '{ cat & wait; }'
diff --git a/bin/sh/tests/execution/bg6.0 b/bin/sh/tests/execution/bg6.0
new file mode 100644
index 000000000000..ce6d88461f97
--- /dev/null
+++ b/bin/sh/tests/execution/bg6.0
@@ -0,0 +1,3 @@
+# The redirection overrides the </dev/null implicit in a background command.
+
+echo yes | ${SH} -c '{ cat & wait; } </dev/stdin'
diff --git a/bin/sh/tests/execution/bg6.0.stdout b/bin/sh/tests/execution/bg6.0.stdout
new file mode 100644
index 000000000000..7cfab5b05d62
--- /dev/null
+++ b/bin/sh/tests/execution/bg6.0.stdout
@@ -0,0 +1 @@
+yes
diff --git a/bin/sh/tests/execution/bg7.0 b/bin/sh/tests/execution/bg7.0
new file mode 100644
index 000000000000..01a0a1a333f3
--- /dev/null
+++ b/bin/sh/tests/execution/bg7.0
@@ -0,0 +1,4 @@
+# The redirection does not apply to the background command, and therefore
+# does not override the implicit </dev/null.
+
+echo bad | ${SH} -c '</dev/null; { cat & wait; }'
diff --git a/bin/sh/tests/execution/bg8.0 b/bin/sh/tests/execution/bg8.0
new file mode 100644
index 000000000000..4eeb235411f3
--- /dev/null
+++ b/bin/sh/tests/execution/bg8.0
@@ -0,0 +1,4 @@
+# The redirection does not apply to the background command, and therefore
+# does not override the implicit </dev/null.
+
+echo bad | ${SH} -c 'command eval \) </dev/null 2>/dev/null; { cat & wait; }'
diff --git a/bin/sh/tests/execution/bg9.0 b/bin/sh/tests/execution/bg9.0
new file mode 100644
index 000000000000..805c90a9caba
--- /dev/null
+++ b/bin/sh/tests/execution/bg9.0
@@ -0,0 +1,4 @@
+# The redirection does not apply to the background command, and therefore
+# does not override the implicit </dev/null.
+
+echo bad | ${SH} -c 'command eval eval \\\) \</dev/null 2>/dev/null; { cat & wait; }'
diff --git a/bin/sh/tests/execution/env1.0 b/bin/sh/tests/execution/env1.0
new file mode 100644
index 000000000000..f1abad21bade
--- /dev/null
+++ b/bin/sh/tests/execution/env1.0
@@ -0,0 +1,4 @@
+
+unset somestrangevar
+export somestrangevar
+[ "`$SH -c 'echo ${somestrangevar-unset}'`" = unset ]
diff --git a/bin/sh/tests/execution/fork1.0 b/bin/sh/tests/execution/fork1.0
new file mode 100644
index 000000000000..bf47ca044306
--- /dev/null
+++ b/bin/sh/tests/execution/fork1.0
@@ -0,0 +1,9 @@
+
+shname=${SH%% *}
+shname=${shname##*/}
+
+result=$(${SH} -c 'ps -p $$ -o comm=')
+test "$result" = "ps" || exit 1
+
+result=$(${SH} -c 'ps -p $$ -o comm=; :')
+test "$result" = "$shname" || exit 1
diff --git a/bin/sh/tests/execution/fork2.0 b/bin/sh/tests/execution/fork2.0
new file mode 100644
index 000000000000..1b2ed28672ca
--- /dev/null
+++ b/bin/sh/tests/execution/fork2.0
@@ -0,0 +1,8 @@
+
+result=$(${SH} -c '(/bin/sleep 1)& sleep 0.1; ps -p $! -o comm=; kill $!')
+test "$result" = sleep || exit 1
+
+result=$(${SH} -c '{ trap "echo trapped" EXIT; (/usr/bin/true); } & wait')
+test "$result" = trapped || exit 1
+
+exit 0
diff --git a/bin/sh/tests/execution/fork3.0 b/bin/sh/tests/execution/fork3.0
new file mode 100644
index 000000000000..d9b2efb235bd
--- /dev/null
+++ b/bin/sh/tests/execution/fork3.0
@@ -0,0 +1,3 @@
+
+result=$(${SH} -c 'f() { ps -p $$ -o comm=; }; f')
+test "$result" = "ps"
diff --git a/bin/sh/tests/execution/func1.0 b/bin/sh/tests/execution/func1.0
new file mode 100644
index 000000000000..bfcdd67ceb4c
--- /dev/null
+++ b/bin/sh/tests/execution/func1.0
@@ -0,0 +1,3 @@
+
+MALLOC_CONF=junk:true ${SH} -c 'g() { g() { :; }; :; }; g' &&
+MALLOC_CONF=junk:true ${SH} -c 'g() { unset -f g; :; }; g'
diff --git a/bin/sh/tests/execution/func2.0 b/bin/sh/tests/execution/func2.0
new file mode 100644
index 000000000000..d0f505e30481
--- /dev/null
+++ b/bin/sh/tests/execution/func2.0
@@ -0,0 +1,11 @@
+# The empty pairs of braces here are to test that this does not cause a crash.
+
+f() { }
+f
+hash -v f >/dev/null
+f() { { }; }
+f
+hash -v f >/dev/null
+f() { { } }
+f
+hash -v f >/dev/null
diff --git a/bin/sh/tests/execution/func3.0 b/bin/sh/tests/execution/func3.0
new file mode 100644
index 000000000000..51e70bfa8ac2
--- /dev/null
+++ b/bin/sh/tests/execution/func3.0
@@ -0,0 +1,6 @@
+
+# This may fail when parsing or when defining the function, or the definition
+# may silently do nothing. In no event may the function be executed.
+
+${SH} -c 'unset() { echo overriding function executed, bad; }; v=1; unset v; exit "${v-0}"' 2>/dev/null
+:
diff --git a/bin/sh/tests/execution/hash1.0 b/bin/sh/tests/execution/hash1.0
new file mode 100644
index 000000000000..f41d38eb4a3c
--- /dev/null
+++ b/bin/sh/tests/execution/hash1.0
@@ -0,0 +1,11 @@
+
+T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
+trap 'rm -rf "${T}"' 0
+PATH=$T:$PATH
+ls -ld . >/dev/null
+cat <<EOF >"$T/ls"
+:
+EOF
+chmod 755 "$T/ls"
+PATH=$PATH
+ls -ld .
diff --git a/bin/sh/tests/execution/int-cmd1.0 b/bin/sh/tests/execution/int-cmd1.0
new file mode 100644
index 000000000000..05d08dc3d62d
--- /dev/null
+++ b/bin/sh/tests/execution/int-cmd1.0
@@ -0,0 +1,2 @@
+
+! echo echo bad | ENV= $SH -ic 'fi' 2>/dev/null
diff --git a/bin/sh/tests/execution/killed1.0 b/bin/sh/tests/execution/killed1.0
new file mode 100644
index 000000000000..a3977b6ce10c
--- /dev/null
+++ b/bin/sh/tests/execution/killed1.0
@@ -0,0 +1,7 @@
+# Sometimes the "Killed" message is not flushed soon enough and it
+# is redirected along with the output of a builtin.
+# Do not change the semicolon to a newline as it would hide the bug.
+
+exec 3>&1
+exec >/dev/null 2>&1
+${SH} -c 'kill -9 $$'; : >&3 2>&3
diff --git a/bin/sh/tests/execution/killed2.0 b/bin/sh/tests/execution/killed2.0
new file mode 100644
index 000000000000..2b9a8fa628e1
--- /dev/null
+++ b/bin/sh/tests/execution/killed2.0
@@ -0,0 +1,9 @@
+# Most shells print a message when a foreground job is killed by a signal.
+# POSIX allows this, provided the message is sent to stderr, not stdout.
+# Some trickery is needed to capture the message as redirecting stderr of
+# the command itself does not affect it. The colon command ensures that
+# the subshell forks for ${SH}.
+
+exec 3>&1
+r=`(${SH} -c 'kill $$'; :) 2>&1 >&3`
+[ -n "$r" ]
diff --git a/bin/sh/tests/execution/not1.0 b/bin/sh/tests/execution/not1.0
new file mode 100644
index 000000000000..86bd3fbe04d3
--- /dev/null
+++ b/bin/sh/tests/execution/not1.0
@@ -0,0 +1,3 @@
+
+f() { ! return $1; }
+f 0 && ! f 1
diff --git a/bin/sh/tests/execution/not2.0 b/bin/sh/tests/execution/not2.0
new file mode 100644
index 000000000000..896f59528c60
--- /dev/null
+++ b/bin/sh/tests/execution/not2.0
@@ -0,0 +1,5 @@
+
+while :; do
+ ! break
+ exit 3
+done
diff --git a/bin/sh/tests/execution/path1.0 b/bin/sh/tests/execution/path1.0
new file mode 100644
index 000000000000..72537dac4973
--- /dev/null
+++ b/bin/sh/tests/execution/path1.0
@@ -0,0 +1,14 @@
+# Some builtins should not be overridable via PATH.
+
+set -e
+T=$(mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX)
+trap 'rm -rf ${T}' 0
+echo '#!/bin/sh
+echo bad' >"$T/cd"
+chmod 755 "$T/cd"
+cd /bin
+oPATH=$PATH
+PATH=$T:$PATH:%builtin
+cd /
+PATH=$oPATH
+[ "$(pwd)" = / ]
diff --git a/bin/sh/tests/execution/pipefail1.0 b/bin/sh/tests/execution/pipefail1.0
new file mode 100644
index 000000000000..d3ce51b3042b
--- /dev/null
+++ b/bin/sh/tests/execution/pipefail1.0
@@ -0,0 +1,3 @@
+
+set -o pipefail
+: && : | : && : | : | : && : | : | : | :
diff --git a/bin/sh/tests/execution/pipefail2.42 b/bin/sh/tests/execution/pipefail2.42
new file mode 100644
index 000000000000..93eded1deda3
--- /dev/null
+++ b/bin/sh/tests/execution/pipefail2.42
@@ -0,0 +1,3 @@
+
+set -o pipefail
+(exit 42) | :
diff --git a/bin/sh/tests/execution/pipefail3.42 b/bin/sh/tests/execution/pipefail3.42
new file mode 100644
index 000000000000..996a404a294c
--- /dev/null
+++ b/bin/sh/tests/execution/pipefail3.42
@@ -0,0 +1,3 @@
+
+set -o pipefail
+: | (exit 42)
diff --git a/bin/sh/tests/execution/pipefail4.42 b/bin/sh/tests/execution/pipefail4.42
new file mode 100644
index 000000000000..d18d36bf470b
--- /dev/null
+++ b/bin/sh/tests/execution/pipefail4.42
@@ -0,0 +1,3 @@
+
+set -o pipefail
+(exit 43) | (exit 42)
diff --git a/bin/sh/tests/execution/pipefail5.42 b/bin/sh/tests/execution/pipefail5.42
new file mode 100644
index 000000000000..3ccfb5d24940
--- /dev/null
+++ b/bin/sh/tests/execution/pipefail5.42
@@ -0,0 +1,4 @@
+
+set -o pipefail
+(exit 42) | : &
+wait %+
diff --git a/bin/sh/tests/execution/pipefail6.42 b/bin/sh/tests/execution/pipefail6.42
new file mode 100644
index 000000000000..4fbca1b09ad8
--- /dev/null
+++ b/bin/sh/tests/execution/pipefail6.42
@@ -0,0 +1,5 @@
+
+set -o pipefail
+(exit 42) | : &
+set +o pipefail
+wait %+
diff --git a/bin/sh/tests/execution/pipefail7.0 b/bin/sh/tests/execution/pipefail7.0
new file mode 100644
index 000000000000..84c551bdb6a3
--- /dev/null
+++ b/bin/sh/tests/execution/pipefail7.0
@@ -0,0 +1,4 @@
+
+(exit 42) | : &
+set -o pipefail
+wait %+
diff --git a/bin/sh/tests/execution/redir1.0 b/bin/sh/tests/execution/redir1.0
new file mode 100644
index 000000000000..ffdc9c82a23d
--- /dev/null
+++ b/bin/sh/tests/execution/redir1.0
@@ -0,0 +1,26 @@
+trap ': $((brokenpipe+=1))' PIPE
+
+P=${TMPDIR:-/tmp}
+cd $P
+T=$(mktemp -d sh-test.XXXXXX)
+cd $T
+
+brokenpipe=0
+mkfifo fifo1 fifo2
+read dummy >fifo2 <fifo1 &
+{
+ exec 4>fifo2
+} 3<fifo2 # Formerly, sh would keep fd 3 and a duplicate of it open.
+echo dummy >fifo1
+if [ $brokenpipe -ne 0 ]; then
+ rc=3
+fi
+wait
+echo dummy >&4 2>/dev/null
+if [ $brokenpipe -eq 1 ]; then
+ : ${rc:=0}
+fi
+
+rm fifo1 fifo2
+rmdir ${P}/${T}
+exit ${rc:-3}
diff --git a/bin/sh/tests/execution/redir2.0 b/bin/sh/tests/execution/redir2.0
new file mode 100644
index 000000000000..4eb44aa3a5bf
--- /dev/null
+++ b/bin/sh/tests/execution/redir2.0
@@ -0,0 +1,28 @@
+trap ': $((brokenpipe+=1))' PIPE
+
+P=${TMPDIR:-/tmp}
+cd $P
+T=$(mktemp -d sh-test.XXXXXX)
+cd $T
+
+brokenpipe=0
+mkfifo fifo1 fifo2
+{
+ {
+ exec ${SH} -c 'exec <fifo1; read dummy'
+ } 7<&- # fifo2 should be kept open, but not passed to programs
+ true
+} 7<fifo2 &
+
+exec 4>fifo2
+exec 3>fifo1
+echo dummy >&4 2>/dev/null
+if [ $brokenpipe -eq 1 ]; then
+ : ${rc:=0}
+fi
+echo dummy >&3
+wait
+
+rm fifo1 fifo2
+rmdir ${P}/${T}
+exit ${rc:-3}
diff --git a/bin/sh/tests/execution/redir3.0 b/bin/sh/tests/execution/redir3.0
new file mode 100644
index 000000000000..3129abbee0b3
--- /dev/null
+++ b/bin/sh/tests/execution/redir3.0
@@ -0,0 +1,2 @@
+
+3>&- 3>&-
diff --git a/bin/sh/tests/execution/redir4.0 b/bin/sh/tests/execution/redir4.0
new file mode 100644
index 000000000000..bee2bd78f5b2
--- /dev/null
+++ b/bin/sh/tests/execution/redir4.0
@@ -0,0 +1,3 @@
+
+{ echo bad 0>&3; } 2>/dev/null 3>/dev/null 3>&-
+exit 0
diff --git a/bin/sh/tests/execution/redir5.0 b/bin/sh/tests/execution/redir5.0
new file mode 100644
index 000000000000..d810475bfb1a
--- /dev/null
+++ b/bin/sh/tests/execution/redir5.0
@@ -0,0 +1,2 @@
+
+{ (echo bad) >/dev/null; } </dev/null
diff --git a/bin/sh/tests/execution/redir6.0 b/bin/sh/tests/execution/redir6.0
new file mode 100644
index 000000000000..d9a90a97523c
--- /dev/null
+++ b/bin/sh/tests/execution/redir6.0
@@ -0,0 +1,20 @@
+
+failures=0
+
+check() {
+ if [ "$2" != "$3" ]; then
+ echo "Failure at $1" >&2
+ failures=$((failures + 1))
+ fi
+}
+
+check $LINENO "$(trap "echo bye" EXIT; : >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; { :; } >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; (:) >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; (: >/dev/null))" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; : >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; { :; } >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; (:) >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; (: >/dev/null)')" bye
+
+exit $((failures > 0))
diff --git a/bin/sh/tests/execution/redir7.0 b/bin/sh/tests/execution/redir7.0
new file mode 100644
index 000000000000..59abf0698493
--- /dev/null
+++ b/bin/sh/tests/execution/redir7.0
@@ -0,0 +1,20 @@
+
+failures=0
+
+check() {
+ if [ "$2" != "$3" ]; then
+ echo "Failure at $1" >&2
+ failures=$((failures + 1))
+ fi
+}
+
+check $LINENO "$(trap "echo bye" EXIT; f() { :; }; f >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; f() { :; }; { f; } >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; f() { :; }; (f) >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; f() { :; }; (f >/dev/null))" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; f() { :; }; f >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; f() { :; }; { f; } >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; f() { :; }; (f) >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; f() { :; }; (f >/dev/null)')" bye
+
+exit $((failures > 0))
diff --git a/bin/sh/tests/execution/set-C1.0 b/bin/sh/tests/execution/set-C1.0
new file mode 100644
index 000000000000..50ce8483c2d6
--- /dev/null
+++ b/bin/sh/tests/execution/set-C1.0
@@ -0,0 +1,11 @@
+
+T=$(mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX") || exit
+trap 'rm -rf "$T"' 0
+
+set -C
+echo . >"$T/a" &&
+[ -s "$T/a" ] &&
+{ ! true >"$T/a"; } 2>/dev/null &&
+[ -s "$T/a" ] &&
+ln -s /dev/null "$T/b" &&
+true >"$T/b"
diff --git a/bin/sh/tests/execution/set-n1.0 b/bin/sh/tests/execution/set-n1.0
new file mode 100644
index 000000000000..e3ee7d2c103d
--- /dev/null
+++ b/bin/sh/tests/execution/set-n1.0
@@ -0,0 +1,6 @@
+
+v=$( ($SH -n <<'EOF'
+for
+EOF
+) 2>&1 >/dev/null)
+[ $? -ne 0 ] && [ -n "$v" ]
diff --git a/bin/sh/tests/execution/set-n2.0 b/bin/sh/tests/execution/set-n2.0
new file mode 100644
index 000000000000..1f309d59f619
--- /dev/null
+++ b/bin/sh/tests/execution/set-n2.0
@@ -0,0 +1,4 @@
+
+$SH -n <<'EOF'
+echo bad
+EOF
diff --git a/bin/sh/tests/execution/set-n3.0 b/bin/sh/tests/execution/set-n3.0
new file mode 100644
index 000000000000..362dd121a1fe
--- /dev/null
+++ b/bin/sh/tests/execution/set-n3.0
@@ -0,0 +1,3 @@
+
+v=$( ($SH -nc 'for') 2>&1 >/dev/null)
+[ $? -ne 0 ] && [ -n "$v" ]
diff --git a/bin/sh/tests/execution/set-n4.0 b/bin/sh/tests/execution/set-n4.0
new file mode 100644
index 000000000000..80a8c2bbcc46
--- /dev/null
+++ b/bin/sh/tests/execution/set-n4.0
@@ -0,0 +1,2 @@
+
+$SH -nc 'echo bad'
diff --git a/bin/sh/tests/execution/set-x1.0 b/bin/sh/tests/execution/set-x1.0
new file mode 100644
index 000000000000..31dffe45d84d
--- /dev/null
+++ b/bin/sh/tests/execution/set-x1.0
@@ -0,0 +1,7 @@
+
+key='must_contain_this'
+{ r=`set -x; { : "$key"; } 2>&1 >/dev/null`; } 2>/dev/null
+case $r in
+*"$key"*) true ;;
+*) false ;;
+esac
diff --git a/bin/sh/tests/execution/set-x2.0 b/bin/sh/tests/execution/set-x2.0
new file mode 100644
index 000000000000..a1b8d6d37f79
--- /dev/null
+++ b/bin/sh/tests/execution/set-x2.0
@@ -0,0 +1,8 @@
+
+key='must contain this'
+PS4="$key+ "
+{ r=`set -x; { :; } 2>&1 >/dev/null`; } 2>/dev/null
+case $r in
+*"$key"*) true ;;
+*) false ;;
+esac
diff --git a/bin/sh/tests/execution/set-x3.0 b/bin/sh/tests/execution/set-x3.0
new file mode 100644
index 000000000000..11f79ea5fcb9
--- /dev/null
+++ b/bin/sh/tests/execution/set-x3.0
@@ -0,0 +1,8 @@
+
+key='must contain this'
+PS4='$key+ '
+{ r=`set -x; { :; } 2>&1 >/dev/null`; } 2>/dev/null
+case $r in
+*"$key"*) true ;;
+*) false ;;
+esac
diff --git a/bin/sh/tests/execution/set-x4.0 b/bin/sh/tests/execution/set-x4.0
new file mode 100644
index 000000000000..495a2d9c304c
--- /dev/null
+++ b/bin/sh/tests/execution/set-x4.0
@@ -0,0 +1,6 @@
+
+key=`printf '\r\t\001\200\300'`
+r=`{ set -x; : "$key"; } 2>&1 >/dev/null`
+case $r in
+*[![:print:]]*) echo fail; exit 3
+esac
diff --git a/bin/sh/tests/execution/shellproc1.0 b/bin/sh/tests/execution/shellproc1.0
new file mode 100644
index 000000000000..125a177f8418
--- /dev/null
+++ b/bin/sh/tests/execution/shellproc1.0
@@ -0,0 +1,10 @@
+
+T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
+trap 'rm -rf "${T}"' 0
+cat <<EOF >"$T/testshellproc"
+printf 'this '
+echo is a test
+EOF
+chmod 755 "$T/testshellproc"
+PATH=$T:$PATH
+[ "`testshellproc`" = "this is a test" ]
diff --git a/bin/sh/tests/execution/shellproc2.0 b/bin/sh/tests/execution/shellproc2.0
new file mode 100644
index 000000000000..b599d16527be
--- /dev/null
+++ b/bin/sh/tests/execution/shellproc2.0
@@ -0,0 +1,17 @@
+# This tests a quality of implementation issue.
+# Shells are not required to reject executing binary files as shell scripts
+# but executing, for example, ELF files for a different architecture as
+# shell scripts may have annoying side effects.
+
+T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
+trap 'rm -rf "${T}"' 0
+printf '\0' >"$T/testshellproc"
+chmod 755 "$T/testshellproc"
+if [ ! -s "$T/testshellproc" ]; then
+ printf "printf did not write a NUL character\n" >&2
+ exit 2
+fi
+PATH=$T:$PATH
+errout=`testshellproc 3>&2 2>&1 >&3 3>&-`
+r=$?
+[ "$r" = 126 ] && [ -n "$errout" ]
diff --git a/bin/sh/tests/execution/shellproc3.0 b/bin/sh/tests/execution/shellproc3.0
new file mode 100644
index 000000000000..17026480a90a
--- /dev/null
+++ b/bin/sh/tests/execution/shellproc3.0
@@ -0,0 +1,13 @@
+# This tests a quality of implementation issue.
+# Shells are not required to reject executing binary files as shell scripts
+# but executing, for example, ELF files for a different architecture as
+# shell scripts may have annoying side effects.
+
+T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
+trap 'rm -rf "${T}"' 0
+printf '\177ELF\001!!\011\0\0\0\0\0\0\0\0' >"$T/testshellproc"
+chmod 755 "$T/testshellproc"
+PATH=$T:$PATH
+errout=`testshellproc 3>&2 2>&1 >&3 3>&-`
+r=$?
+[ "$r" = 126 ] && [ -n "$errout" ]
diff --git a/bin/sh/tests/execution/shellproc4.0 b/bin/sh/tests/execution/shellproc4.0
new file mode 100644
index 000000000000..4aa944b55a86
--- /dev/null
+++ b/bin/sh/tests/execution/shellproc4.0
@@ -0,0 +1,13 @@
+# This tests a quality of implementation issue.
+# Shells are not required to reject executing binary files as shell scripts
+# but executing, for example, ELF files for a different architecture as
+# shell scripts may have annoying side effects.
+
+T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
+trap 'rm -rf "${T}"' 0
+printf '\211PNG\015\012\032\012\0\0\0\015IHDR' >"$T/testshellproc"
+chmod 755 "$T/testshellproc"
+PATH=$T:$PATH
+errout=`testshellproc 3>&2 2>&1 >&3 3>&-`
+r=$?
+[ "$r" = 126 ] && [ -n "$errout" ]
diff --git a/bin/sh/tests/execution/shellproc5.0 b/bin/sh/tests/execution/shellproc5.0
new file mode 100644
index 000000000000..535e5dabc4d9
--- /dev/null
+++ b/bin/sh/tests/execution/shellproc5.0
@@ -0,0 +1,13 @@
+# This tests a quality of implementation issue.
+# Shells are not required to reject executing binary files as shell scripts
+# but executing, for example, ELF files for a different architecture as
+# shell scripts may have annoying side effects.
+
+T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
+trap 'rm -rf "${T}"' 0
+printf '\177ELF\001!!\012\0\0\0\0\0\0\0\0' >"$T/testshellproc"
+chmod 755 "$T/testshellproc"
+PATH=$T:$PATH
+errout=`testshellproc 3>&2 2>&1 >&3 3>&-`
+r=$?
+[ "$r" = 126 ] && [ -n "$errout" ]
diff --git a/bin/sh/tests/execution/shellproc6.0 b/bin/sh/tests/execution/shellproc6.0
new file mode 100644
index 000000000000..f1527f6d854d
--- /dev/null
+++ b/bin/sh/tests/execution/shellproc6.0
@@ -0,0 +1,7 @@
+
+T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
+trap 'rm -rf "${T}"' 0
+printf 'printf "this "\necho is a test\nexit\n\0' >"$T/testshellproc"
+chmod 755 "$T/testshellproc"
+PATH=$T:$PATH
+[ "`testshellproc`" = "this is a test" ]
diff --git a/bin/sh/tests/execution/shellproc7.0 b/bin/sh/tests/execution/shellproc7.0
new file mode 100644
index 000000000000..b5e543826c8a
--- /dev/null
+++ b/bin/sh/tests/execution/shellproc7.0
@@ -0,0 +1,9 @@
+# Non-POSIX trickery that is widely supported,
+# used by https://justine.lol/ape.html
+
+T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
+trap 'rm -rf "${T}"' 0
+printf "MZqFpD='\n\0'\n#'\"\necho this is a test\n" >"$T/testshellproc"
+chmod 755 "$T/testshellproc"
+PATH=$T:$PATH
+[ "`testshellproc`" = "this is a test" ]
diff --git a/bin/sh/tests/execution/subshell1.0 b/bin/sh/tests/execution/subshell1.0
new file mode 100644
index 000000000000..ddff2fee4999
--- /dev/null
+++ b/bin/sh/tests/execution/subshell1.0
@@ -0,0 +1,5 @@
+
+(eval "cd /
+v=$(printf %0100000d 1)
+echo \${#v}")
+echo end
diff --git a/bin/sh/tests/execution/subshell1.0.stdout b/bin/sh/tests/execution/subshell1.0.stdout
new file mode 100644
index 000000000000..8c71af3cd79f
--- /dev/null
+++ b/bin/sh/tests/execution/subshell1.0.stdout
@@ -0,0 +1,2 @@
+100000
+end
diff --git a/bin/sh/tests/execution/subshell2.0 b/bin/sh/tests/execution/subshell2.0
new file mode 100644
index 000000000000..ad5a3b87af47
--- /dev/null
+++ b/bin/sh/tests/execution/subshell2.0
@@ -0,0 +1,9 @@
+
+f() {
+ x=2
+}
+(
+ x=1
+ f
+ [ "$x" = 2 ]
+)
diff --git a/bin/sh/tests/execution/subshell3.0 b/bin/sh/tests/execution/subshell3.0
new file mode 100644
index 000000000000..4d1916dfa18e
--- /dev/null
+++ b/bin/sh/tests/execution/subshell3.0
@@ -0,0 +1,3 @@
+
+(false; exit) && exit 3
+exit 0
diff --git a/bin/sh/tests/execution/subshell4.0 b/bin/sh/tests/execution/subshell4.0
new file mode 100644
index 000000000000..841186b5e619
--- /dev/null
+++ b/bin/sh/tests/execution/subshell4.0
@@ -0,0 +1,2 @@
+
+(eval "set v=1"; false) && echo bad; :
diff --git a/bin/sh/tests/execution/unknown1.0 b/bin/sh/tests/execution/unknown1.0
new file mode 100644
index 000000000000..c41243454dbc
--- /dev/null
+++ b/bin/sh/tests/execution/unknown1.0
@@ -0,0 +1,28 @@
+
+nosuchtool 2>/dev/null
+[ $? -ne 127 ] && exit 1
+/var/empty/nosuchtool 2>/dev/null
+[ $? -ne 127 ] && exit 1
+(nosuchtool) 2>/dev/null
+[ $? -ne 127 ] && exit 1
+(/var/empty/nosuchtool) 2>/dev/null
+[ $? -ne 127 ] && exit 1
+/ 2>/dev/null
+[ $? -ne 126 ] && exit 1
+PATH=/usr bin 2>/dev/null
+[ $? -ne 126 ] && exit 1
+
+dummy=$(nosuchtool 2>/dev/null)
+[ $? -ne 127 ] && exit 1
+dummy=$(/var/empty/nosuchtool 2>/dev/null)
+[ $? -ne 127 ] && exit 1
+dummy=$( (nosuchtool) 2>/dev/null)
+[ $? -ne 127 ] && exit 1
+dummy=$( (/var/empty/nosuchtool) 2>/dev/null)
+[ $? -ne 127 ] && exit 1
+dummy=$(/ 2>/dev/null)
+[ $? -ne 126 ] && exit 1
+dummy=$(PATH=/usr bin 2>/dev/null)
+[ $? -ne 126 ] && exit 1
+
+exit 0
diff --git a/bin/sh/tests/execution/unknown2.0 b/bin/sh/tests/execution/unknown2.0
new file mode 100644
index 000000000000..eb7ab0175a65
--- /dev/null
+++ b/bin/sh/tests/execution/unknown2.0
@@ -0,0 +1,5 @@
+
+{
+ : $(/var/empty/nosuchtool)
+ : $(:)
+} 2>/dev/null
diff --git a/bin/sh/tests/execution/var-assign1.0 b/bin/sh/tests/execution/var-assign1.0
new file mode 100644
index 000000000000..8d49498d848e
--- /dev/null
+++ b/bin/sh/tests/execution/var-assign1.0
@@ -0,0 +1,2 @@
+
+[ "$(HOME=/etc HOME=/ cd && pwd)" = / ]