New feature SHELL address
diff --git a/CHANGES b/CHANGES
index 550cb53..aeda542 100644
--- a/CHANGES
+++ b/CHANGES
@@ -133,6 +133,8 @@
 	Tests: LINUX_POSIXMQ_READ_PRIO LINUX_POSIXMQ_RECV_FORK
 	LINUX_POSIXMQ_RECV_MAXCHILDREN LINUX_POSIXMQ_SEND_MAXCHILDREN
 
+	New address SHELL invokes a shell but without the overhead of SYSTEM
+
 Corrections:
 	When a sub process (EXEC, SYSTEM) terminated with exit code other than
 	0, its last sent data might have been lost depending on timing of read/
diff --git a/Makefile.in b/Makefile.in
index dd46d7a..3f0c1bf 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -50,7 +50,8 @@
 	xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \
 	xio-sctp.c xio-rawip.c xio-posixmq.c \
 	xio-socks.c xio-socks5.c xio-proxy.c xio-udp.c \
-	xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
+	xio-progcall.c xio-exec.c xio-system.c xio-shell.c \
+	xio-termios.c xio-readline.c \
 	xio-pty.c xio-openssl.c xio-streams.c xio-namespaces.c \
 	xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-fs.c xio-tun.c
 XIOOBJS = $(XIOSRCS:.c=.o)
@@ -68,7 +69,7 @@
 	xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h xio-posixmq.h \
 	xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \
 	xio-socks.h xio-socks5.h xio-proxy.h xio-progcall.h xio-exec.h \
-	xio-system.h xio-termios.h xio-readline.h \
+	xio-system.h xio-shell.h xio-termios.h xio-readline.h \
 	xio-pty.h xio-openssl.h xio-streams.h xio-namespaces.h \
 	xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-fs.h xio-tun.h
 
diff --git a/config.h.in b/config.h.in
index f24152d..15833ed 100644
--- a/config.h.in
+++ b/config.h.in
@@ -713,6 +713,7 @@
 #undef WITH_PROXY
 #undef WITH_EXEC
 #undef WITH_SYSTEM
+#undef WITH_SHELL
 #undef WITH_READLINE
 #undef WITH_TUN
 #undef WITH_PTY
diff --git a/configure.ac b/configure.ac
index 90362c0..338f427 100644
--- a/configure.ac
+++ b/configure.ac
@@ -489,6 +489,14 @@
 	       esac],
 	       [AC_DEFINE(WITH_SYSTEM) AC_MSG_RESULT(yes)])
 
+AC_MSG_CHECKING([whether to include shell invocation support])
+AC_ARG_ENABLE(system, [  --disable-shell         disable shell invocation support],
+	      [case "$enableval" in
+	       no) AC_MSG_RESULT(no);;
+	       *) AC_DEFINE(WITH_SHELL) AC_MSG_RESULT(yes);;
+	       esac],
+	       [AC_DEFINE(WITH_SHELL) AC_MSG_RESULT(yes)])
+
 AC_MSG_CHECKING(whether to include pty address support)
 AC_ARG_ENABLE(pty, [  --disable-pty           disable pty support],
 	      [case "$enableval" in
diff --git a/doc/socat.yo b/doc/socat.yo
index 8ba7fa1..fe7bffd 100644
--- a/doc/socat.yo
+++ b/doc/socat.yo
@@ -335,6 +335,7 @@
    link(su)(OPTION_SUBSTUSER),
    link(su-d)(OPTION_SUBSTUSER_DELAYED),
    link(nofork)(OPTION_NOFORK),
+   link(socktype)(OPTION_SO_TYPE),
    link(pty)(OPTION_PTY),
    link(stderr)(OPTION_STDERR),
    link(ctty)(OPTION_CTTY),
@@ -344,7 +345,7 @@
    link(sigint)(OPTION_SIGINT),
    link(sigquit)(OPTION_SIGQUIT),
    link(netns)(OPTION_NETNS)nl()
-   See also: link(SYSTEM)(ADDRESS_SYSTEM)
+   See also: link(SYSTEM)(ADDRESS_SYSTEM),link(SHELL)(ADDRESS_SHELL)
 label(ADDRESS_FD)dit(bf(tt(FD:<fdnum>)))
    Uses the file descriptor link(<fdnum>)(TYPE_FDNUM). It must already exist as
    valid unix() file descriptor.nl()
@@ -785,7 +786,7 @@
    See also:
    link(UNIX-LISTEN)(ADDRESS_UNIX_LISTEN),
    link(PIPE)(ADDRESS_NAMED_PIPE),
-   link(EXEC)(ADDRESS_EXEC), link(SYSTEM)(ADDRESS_SYSTEM)
+   link(EXEC)(ADDRESS_EXEC), link(SYSTEM)(ADDRESS_SYSTEM), link(SHELL)(ADDRESS_SHELL)
 label(ADDRESS_READLINE)dit(bf(tt(READLINE)))
    Uses GNU readline and history on stdio to allow editing and reusing input
    lines (link(example)(EXAMPLE_ADDRESS_READLINE)). This requires the GNU readline and 
@@ -1087,6 +1088,32 @@
    link(-U)(option_U), and link(dual addresses)(ADDRESS_DUAL).nl()
    Option groups: link(FD)(GROUP_FD) (link(TERMIOS)(GROUP_TERMIOS),link(REG)(GROUP_REG),link(SOCKET)(GROUP_SOCKET)) nl()
    See also: link(FD)(ADDRESS_FD)
+label(ADDRESS_SHELL)dit(bf(tt(SHELL:<shell-command>)))
+   Forks a sub process that establishes communication with its parent process
+   and invokes the specified program with the configured shell ($SHELL).
+   Note that <shell-command> [link(string)(TYPE_STRING)] must
+   not contain ',' or "!!", and that shell meta characters may have to be
+   protected.
+   After successful program start, socat() writes data to stdin of the 
+   process and reads from its stdout.nl()
+   Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(EXEC)(GROUP_EXEC),link(FORK)(GROUP_FORK),link(TERMIOS)(GROUP_TERMIOS) nl()
+   Useful options:
+   link(path)(OPTION_PATH),
+   link(fdin)(OPTION_FDIN),
+   link(fdout)(OPTION_FDOUT),
+   link(chroot)(OPTION_CHROOT),
+   link(su)(OPTION_SUBSTUSER),
+   link(su-d)(OPTION_SUBSTUSER_DELAYED),
+   link(nofork)(OPTION_NOFORK),
+   link(socktype)(OPTION_SO_TYPE),
+   link(pty)(OPTION_PTY),
+   link(stderr)(OPTION_STDERR),
+   link(ctty)(OPTION_CTTY),
+   link(setsid)(OPTION_SETSID),
+   link(pipes)(OPTION_PIPES),
+   link(sigint)(OPTION_SIGINT),
+   link(sigquit)(OPTION_SIGQUIT)nl()
+   See also: link(EXEC)(ADDRESS_EXEC), link(SYSTEM)(ADDRESS_SYSTEM)
 label(ADDRESS_SYSTEM)dit(bf(tt(SYSTEM:<shell-command>)))
    Forks a sub process that establishes communication with its parent process
    and invokes the specified program with code(system()). Please note that
@@ -1104,6 +1131,7 @@
    link(su)(OPTION_SUBSTUSER),
    link(su-d)(OPTION_SUBSTUSER_DELAYED),
    link(nofork)(OPTION_NOFORK),
+   link(socktype)(OPTION_SO_TYPE),
    link(pty)(OPTION_PTY),
    link(stderr)(OPTION_STDERR),
    link(ctty)(OPTION_CTTY),
@@ -1112,7 +1140,7 @@
    link(sigint)(OPTION_SIGINT),
    link(sigquit)(OPTION_SIGQUIT),
    link(netns)(OPTION_NETNS)nl()
-   See also: link(EXEC)(ADDRESS_EXEC)
+   See also: link(EXEC)(ADDRESS_EXEC), link(SHELL)(ADDRESS_SHELL)
 label(ADDRESS_TCP_CONNECT)dit(bf(tt(TCP:<host>:<port>)))
    Connects to <port> [link(TCP service)(TYPE_TCP_SERVICE)] on
    <host> [link(IP address)(TYPE_IP_ADDRESS)] using TCP/IP version 4 or 6
@@ -2163,6 +2191,7 @@
    [link(int)(TYPE_INT)]. Address resolution is not affected by this option.
    Under Linux, 1 means stream oriented socket, 2 means datagram socket, 3
    means raw socket, and 5 seqpacket (stream keeping packet boundaries).
+   Datagrams are useful when you want to keep packet boundaries.
 label(OPTION_SO_PROTOCOL)dit(bf(tt(protocol)))
    Sets the protocol of the socket, specified as third argument to the
    code(socket()) or code(socketpair()) calls, to <protocol>
@@ -2786,6 +2815,19 @@
 startdit()enddit()nl()
 
 
+label(GROUP_SHELL)
+
+Options for link(address SHELL)(ADDRESS_SHELL)
+
+label(OPTION_SHELL)dit(bf(tt(shell=<filename>)))
+   Overwrites use the default shell with the named executable, e.g.
+   tt(/bin/dash). Also sets the tt(SHELL) environment variable.
+
+enddit()
+
+startdit()enddit()nl()
+
+
 label(GROUP_TERMIOS)em(bf(TERMIOS option group))
 
 For addresses that work on a tty (e.g., stdio, file:/dev/tty, exec:...,pty), the terminal parameters defined in the unix() termios mechanism are made available as address option parameters.
@@ -4409,8 +4451,8 @@
 
 dit(bf(SOCAT_PID) (output)) Socat sets this variable to its process id. In case
 of link(fork)(OPTION_FORK) address option, SOCAT_PID gets the child processes
-id. Forking for link(exec)(ADDRESS_EXEC) and link(system)(ADDRESS_SYSTEM) does
-not change SOCAT_PID.
+id. Forking for link(exec)(ADDRESS_EXEC), link(system)(ADDRESS_SYSTEM), and
+link(SHELL)(ADDRESS_SHELL) does not change SOCAT_PID.
 
 dit(bf(SOCAT_PPID) (output)) Socat sets this variable to its process id. In
 case of link(fork)(OPTION_FORK), SOCAT_PPID keeps the pid of the master process.
@@ -4506,8 +4548,8 @@
 given user.
 
 dit(bf(PATH) (output))
-Can be set with option link(path)(OPTION_PATH) for link(exec)(ADDRESS_EXEC) and
-link(system)(ADDRESS_SYSTEM) addresses.
+Can be set with option link(path)(OPTION_PATH) for link(exec)(ADDRESS_EXEC),
+link(system)(ADDRESS_SYSTEM), and link(SHELL)(ADDRESS_SHELL) addresses.
 
 dit(bf(HOME) (output))
 With options link(su)(OPTION_SUBSTUSER) and
diff --git a/socat.c b/socat.c
index 864415b..8632093 100644
--- a/socat.c
+++ b/socat.c
@@ -644,6 +644,11 @@
 #else
    fputs("  #undef WITH_SYSTEM\n", fd);
 #endif
+#ifdef WITH_SHELL
+   fprintf(fd, "  #define WITH_SHELL %d\n", WITH_SHELL);
+#else
+   fputs("  #undef WITH_SHELL\n", fd);
+#endif
 #ifdef WITH_EXEC
    fprintf(fd, "  #define WITH_EXEC %d\n", WITH_EXEC);
 #else
diff --git a/test.sh b/test.sh
index 214524a..6e6c98d 100755
--- a/test.sh
+++ b/test.sh
@@ -814,11 +814,11 @@
     return 0
 }
 
-# return a list of child process pids
+# return a list of child process pids [killchild]
 childpids () {
     case "$UNAME" in
     AIX)     l="$(ps -fade |grep "^........ ...... $(printf %6u $1)" |awk '{print($2);}')" ;;
-    FreeBSD) l="$(ps -fl   |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]*[ ][ ]*$(printf %5u $1)" |awk '{print($2);}')" ;;
+    FreeBSD) l="$(ps -fl   |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]*[ ][ ]*$1[ ]" |awk '{print($2);}')" ;;
     HP-UX)   l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;;
 #    Linux)   l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;;
     Linux)   l="$(ps -fade |grep "^[^[:space:]][^[:space:]]*[[:space:]][[:space:]]*[^[:space:]][^[:space:]]*[[:space:]][[:space:]]*$1 " |awk '{print($2);}')" ;;
@@ -4466,7 +4466,7 @@
     numCANT=$((numCANT+1))
     listCANT="$listCANT $N"
 else
-SAVETERM="$TERM"; TERM=	# 'cause konsole might print controls even in raw
+SAVETERM="$TERM"; TERM=	# 'cause console might print controls even in raw
 SAVEMICS=$MICROS
 #MICROS=2000000
 ts="$td/test$N.sh"
@@ -4478,7 +4478,7 @@
 tdiff="$td/test$N.diff"
 da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
 # the feature that we really want to test is in the readline.sh script:
-CMD="$TRACE $SOCAT $opts -t1 open:$tpi,nonblock!!open:$tpo exec:\"./readline.sh -nh ./readline-test.sh\",pty,ctty,setsid,raw,echo=0,isig"
+CMD="$TRACE $SOCAT -lpwrapper $opts -t1 open:$tpi,nonblock!!open:$tpo exec:\"./readline.sh -nh ./readline-test.sh\",pty,ctty,setsid,raw,echo=0,isig"
 #echo "$CMD" >"$ts"
 #chmod a+x "$ts"
 printf "test $F_n $TEST... " $N
@@ -4487,6 +4487,7 @@
 touch "$tpo"
 #
 # during development of this test, the following command line succeeded:
+# ECHO="echo -e" SOCAT=./socat
 # (sleep 1; $ECHO "user\n\c"; sleep 1; $ECHO "password\c"; sleep 1; $ECHO "\n\c"; sleep 1; $ECHO "test 1\n\c"; sleep 1; $ECHO "\003\c"; sleep 1; $ECHO "test 2\n\c"; sleep 1; $ECHO "exit\n\c"; sleep 1) |$TRACE $SOCAT -d -d -d -d -lf/tmp/$USER/debug1 -v -x - exec:'./readline.sh ./readline-test.sh',pty,ctty,setsid,raw,echo=0,isig
 #
 # the following cat, in case of socat failure, reads the pipe to prevent below writer from hanging
@@ -4530,14 +4531,16 @@
 wait
 if ! tr "$($ECHO '\r \c')" "% " <$tpo |sed 's/%$//g' |sed 's/.*%//g' |diff "$tr" - >"$tdiff" 2>&1; then
     $PRINTF "$FAILED: $TRACE $SOCAT:\n"
-    echo "$CMD"
-    cat "$te"
-    cat "$tdiff"
+    echo "$CMD" 2>&1
+    cat "$te" 2>&1
+    echo diff:  2>&1
+    cat "$tdiff" 2>&1
     numFAIL=$((numFAIL+1))
     listFAIL="$listFAIL $N"
 else
    $PRINTF "$OK\n"
-   if [ -n "$debug" ]; then cat $te; fi
+    if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
+    if [ "$DEBUG" ];   then cat "${te}0" >&2; fi
    numOK=$((numOK+1))
 fi
 kill $pid 2>/dev/null	# necc on OpenBSD
@@ -5978,7 +5981,7 @@
 te="$td/test$N.err"
 tdiff="$td/test$N.diff"
 da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
-# the feature that we really want to test is in the readline.sh script:
+#
 CMD="$TRACE $SOCAT $opts -u open:$ti,readbytes=100 -"
 printf "test $F_n $TEST... " $N
 rm -f "$tf" "$ti" "$to"
@@ -17066,21 +17069,21 @@
 N=$((N+1))
 
 
-# Test the sigint option
-NAME=EXEC_SIGINT
+# Test the sigint option with SHELL address
+NAME=SHELL_SIGINT
 case "$TESTS" in
-*%$N%*|*%functions%*|*%socket%*|*%exec%*|*%sigint%*|*%$NAME%*)
-TEST="$NAME: sigint option with EXEC"
+*%$N%*|*%functions%*|*%socket%*|*%shell%*|*%progcall%*|*%sigint%*|*%$NAME%*)
+TEST="$NAME: sigint option with SHELL"
 # Run Socat with an EXEC address invoking Socat, with option sigint
 # Send the parent a SIGINT; when the child gets SIGINT too (vs.SIGTERM)
 # the test succeeded
 if ! eval $NUMCOND; then :;
 # Remove unneeded checks, adapt lists of the remaining ones
-elif ! F=$(testfeats STDIO EXEC PIPE); then
+elif ! F=$(testfeats STDIO SHELL PIPE); then
     $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
     numCANT=$((numCANT+1))
     listCANT="$listCANT $N"
-elif ! A=$(testaddrs STDIO EXEC PIPE); then
+elif ! A=$(testaddrs STDIO SHELL PIPE); then
     $PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
     numCANT=$((numCANT+1))
     listCANT="$listCANT $N"
@@ -17093,8 +17096,11 @@
 te="$td/test$N.stderr"
 tdiff="$td/test$N.diff"
 da="test$N $(date) $RANDOM"
-CMD0="$TRACE $SOCAT $opts -T 2 PIPE EXEC:\"$CAT\",pty,setsid,sigint"
+#CMD0="$TRACE $SOCAT $opts -T 2 PIPE EXEC:\"socat\ -d\ -d\ -d\ -d\ -lu\ PIPE\ PIPE\",pty,setsid,sigint"
+#CMD0="$TRACE $SOCAT $opts -T 2 PIPE EXEC:\"$CAT\",pty,setsid,sigint"
+CMD0="$TRACE $SOCAT $opts -T 2 SOCKETPAIR EXEC:\"$CAT\",pty,setsid,sigint"
 printf "test $F_n $TEST... " $N
+eval $CMD0 >/dev/null 2>"${te}0" &
 $CMD0 >/dev/null 2>"${te}0" &
 pid0=$!
 sleep 1
@@ -17120,6 +17126,167 @@
 N=$((N+1))
 
 
+# Test the SHELL address with socketpair (default)
+NAME=SHELL_SOCKETPAIR
+case "$TESTS" in
+*%$N%*|*%functions%*|*%shell%*|*%socketpair%*|*%$NAME%*)
+TEST="$NAME: simple echo via SHELL of cat with socketpair"
+# testecho ...
+if ! eval $NUMCOND; then :;
+elif ! F=$(testfeats STDIO SHELL); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! A=$(testaddrs STDIO SHELL); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+else
+    testecho "$N" "$TEST" "" "SHELL:$CAT" "$opts" "$val_t"
+fi
+esac
+N=$((N+1))
+
+# Test the SHELL address with pipes
+NAME=SHELL_PIPES
+case "$TESTS" in
+*%$N%*|*%functions%*|*%shell%*|*%pipe%*|*%$NAME%*)
+TEST="$NAME: simple echo via SHELL of cat with pipes"
+# testecho ...
+if ! eval $NUMCOND; then :;
+elif ! F=$(testfeats STDIO SHELL SOCKETPAIR); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! A=$(testaddrs STDIO SHELL PIPE); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+else
+    testecho "$N" "$TEST" "" "SHELL:$CAT,pipes" "$opts" "$val_t"
+fi
+esac
+N=$((N+1))
+
+# Test the SHELL address with pty
+NAME=SHELL_PTY
+case "$TESTS" in
+*%$N%*|*%functions%*|*%shell%*|*%pty%*|*%$NAME%*)
+TEST="$NAME: simple echo via SHELL of cat with pty"
+# testecho ...
+if ! eval $NUMCOND; then :;
+elif ! F=$(testfeats STDIO SHELL PTY); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! A=$(testaddrs STDIO SHELL PTY); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+else
+    testecho "$N" "$TEST" "" "SHELL:$CAT,pty,$PTYOPTS,$PTYOPTS2" "$opts" "$val_t"
+fi
+esac
+N=$((N+1))
+
+# Test the SHELL address halfclose with socketpair
+NAME=SHELL_SOCKETPAIR_FLUSH
+case "$TESTS" in
+*%$N%*|*%functions%*|*%shell%*|*%socketpair%*|*%halfclose%*|*%$NAME%*)
+TEST="$NAME: call  od -c  via SHELL using socketpair"
+# testecho ...
+if ! eval $NUMCOND; then :;
+elif ! F=$(testfeats STDIO SHELL); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! A=$(testaddrs STDIO SHELL); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+else
+    testod "$N" "$TEST" "" "SHELL:$OD_C" "$opts" "$val_t"
+fi
+esac
+N=$((N+1))
+
+# Test SHELL address halfclose with pipes
+NAME=SHELL_PIPES
+case "$TESTS" in
+*%$N%*|*%functions%*|*%shell%*|*%pipe%*|*%halfclose%*|*%$NAME%*)
+TEST="$NAME: call  od -c  via SHELL using pipes"
+# testecho ...
+if ! eval $NUMCOND; then :;
+elif ! F=$(testfeats STDIO SHELL SOCKETPAIR); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! A=$(testaddrs STDIO SHELL PIPE); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+else
+    testod "$N" "$TEST" "" "SHELL:$OD_C,pipes" "$opts" "$val_t"
+fi
+esac
+N=$((N+1))
+
+
+# Test the sigint option with SYSTEM address
+NAME=SYSTEM_SIGINT
+case "$TESTS" in
+*%$N%*|*%functions%*|*%socket%*|*%progcall%*|*%system%*|*%sigint%*|*%$NAME%*)
+TEST="$NAME: sigint option with SYSTEM"
+# Run Socat with a SYSTEM address invoking Socat, with option sigint
+# Send the parent a SIGINT; when the child gets SIGINT too (vs.SIGTERM)
+# the test succeeded
+# setsid is required so the initial SIGINT is not delivered to the sub process.
+if ! eval $NUMCOND; then :;
+# Remove unneeded checks, adapt lists of the remaining ones
+elif ! F=$(testfeats STDIO SYSTEM PIPE); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! A=$(testaddrs STDIO SYSTEM PIPE); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! o=$(testoptions setsid sigint) >/dev/null; then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+else
+tf="$td/test$N.stdout"
+te="$td/test$N.stderr"
+tdiff="$td/test$N.diff"
+da="test$N $(date) $RANDOM"
+#CMD0="$TRACE $SOCAT $opts PIPE SHELL:\"$SOCAT\ -dddd\ -lf ${te}1\ PIPE\ PIPE\",setsid,sigint"
+CMD0="$TRACE $SOCAT $opts SOCKETPAIR SHELL:\"$SOCAT\ -dddd\ -lf ${te}1\ PIPE\ PIPE\",setsid,sigint"
+printf "test $F_n $TEST... " $N
+eval $CMD0 >/dev/null 2>"${te}0" &
+pid0=$!
+sleep 1
+kill -INT $(childpids $pid0)
+wait
+if grep -q " W waitpid..: child .* exited with status 130" "${te}0"; then
+    $PRINTF "$OK\n"
+    if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
+    if [ "$DEBUG" ];   then cat "${te}0" >&2; fi
+    numOK=$((numOK+1))
+else
+    $PRINTF "$FAILED\n"
+    echo "$CMD0 &"
+    cat "${te}0" >&2
+    numFAIL=$((numFAIL+1))
+    listFAIL="$listFAIL $N"
+    namesFAIL="$namesFAIL $NAME"
+fi
+fi # NUMCOND
+ ;;
+esac
+N=$((N+1))
+
+
 # end of common tests
 
 ##################################################################################
@@ -17308,14 +17475,25 @@
 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
 rc1=$?
 kill $pid0 2>/dev/null; wait
-if echo "$da" |diff "${tf}1" - >$tdiff; then
-    $PRINTF "$OK\n"
-    if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
-    if [ "$DEBUG" ];   then cat "${te}0" >&2; fi
-    if [ "$VERBOSE" ]; then echo "$CMD1"; fi
-    if [ "$DEBUG" ];   then cat "${te}1" >&2; fi
-    numOK=$((numOK+1))
-elif [ !?!?! ]; then
+if [ "$rc1" -ne 0 ]; then
+    $PRINTF "$FAILED\n"
+    echo "$CMD0 &"
+    cat "${te}0" >&2
+    echo "$CMD1"
+    cat "${te}1" >&2
+    numFAIL=$((numFAIL+1))
+    listFAIL="$listFAIL $N"
+    namesFAIL="$namesFAIL $NAME"
+elif ! echo "$da" |diff "${tf}1" - >$tdiff; then
+    $PRINTF "$FAILED\n"
+    echo "$CMD0 &"
+    cat "${te}0" >&2
+    echo "$CMD1"
+    cat "${te}1" >&2
+    numFAIL=$((numFAIL+1))
+    listFAIL="$listFAIL $N"
+    namesFAIL="$namesFAIL $NAME"
+elif [ ??? ]; then
     # The test could not run meaningfully
     $PRINTF "$CANT\n"
     if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
@@ -17325,14 +17503,12 @@
     numCANT=$((numCANT+1))
     listCANT="$listCANT $N"
 else
-    $PRINTF "$FAILED\n"
-    echo "$CMD0 &"
-    cat "${te}0" >&2
-    echo "$CMD1"
-    cat "${te}1" >&2
-    numFAIL=$((numFAIL+1))
-    listFAIL="$listFAIL $N"
-    namesFAIL="$namesFAIL $NAME"
+    $PRINTF "$OK\n"
+    if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
+    if [ "$DEBUG" ];   then cat "${te}0" >&2; fi
+    if [ "$VERBOSE" ]; then echo "$CMD1"; fi
+    if [ "$DEBUG" ];   then cat "${te}1" >&2; fi
+    numOK=$((numOK+1))
 fi
 fi # NUMCOND
  ;;
diff --git a/xio-shell.c b/xio-shell.c
new file mode 100644
index 0000000..8a41e21
--- /dev/null
+++ b/xio-shell.c
@@ -0,0 +1,98 @@
+/* source: xio-shell.c */
+/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+/* this file contains the source for opening addresses of shell type */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-progcall.h"
+#include "xio-shell.h"
+
+
+#if WITH_SHELL
+
+static int xioopen_shell(int arg, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
+
+const struct addrdesc xioaddr_shell = { "SHELL", 3, xioopen_shell, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT|GROUP_SHELL, 1, 0, 0 HELP(":<shell-command>") };
+
+const struct optdesc opt_shell = { "shell", NULL, OPT_SHELL, GROUP_SHELL, PH_PREEXEC, TYPE_STRING, OFUNC_SPEC, 0, 0 };
+
+static int xioopen_shell(
+	int argc,
+	const char *argv[],
+	struct opt *opts,
+	int xioflags,
+	xiofile_t *xfd,
+	const struct addrdesc *addrdesc)
+{
+	struct single *sfd = &xfd->stream;
+	int status;
+	char *path = NULL;
+	int duptostderr;
+	int result;
+	char *shellpath = NULL;
+	const char *shellname;
+	const char *string = argv[1];
+
+	if (argc != 2) {
+		xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
+		return STAT_NORETRY;
+	}
+
+	shellpath = getenv("SHELL");
+	retropt_string(opts, OPT_SHELL, &shellpath);
+	if (shellpath == NULL) {
+		Error("SHELL variable undefined");
+		errno = EINVAL;
+		return -1;
+	}
+	shellname = strrchr(shellpath, '/');
+	if (shellname == NULL) {
+		Error1("SHELL \"%s\" variable does not specify a path (has no '/')", shellpath);
+		errno = EINVAL;
+		return -1;
+	}
+	++shellname;
+
+	status = _xioopen_foxec(xioflags, sfd, addrdesc->groups, &opts, &duptostderr);
+	if (status < 0)  return status;
+	if (status == 0) {	/* child */
+		int numleft;
+
+		if (setopt_path(opts, &path) < 0) {
+			/* this could be dangerous, so let us abort this child... */
+			Exit(1);
+		}
+
+		if ((numleft = leftopts(opts)) > 0) {
+			Error1("%d option(s) could not be used", numleft);
+			showleft(opts);
+			return STAT_NORETRY;
+		}
+
+		/* only now redirect stderr */
+		if (duptostderr >= 0) {
+			diag_dup();
+			Dup2(duptostderr, 2);
+		}
+
+		Setenv("SHELL", shellpath, 1);
+
+		Info1("executing shell command \"%s\"", string);
+		Debug3("execl(\"%s\", \"%s\", \"-c\", \"%s\", NULL",
+		       shellpath, shellname, string);
+		result = execl(shellpath, shellname, "-c", string, (char *)NULL);
+		if (result != 0) {
+			Warn2("execl(\"%s\") returned with status %d", string, result);
+			Warn1("execl(): %s", strerror(errno));
+		}
+		Exit(0);	/* this child process */
+	}
+
+	/* parent */
+	return 0;
+}
+
+#endif /* WITH_SHELL */
diff --git a/xio-shell.h b/xio-shell.h
new file mode 100644
index 0000000..7524c25
--- /dev/null
+++ b/xio-shell.h
@@ -0,0 +1,12 @@
+/* source: xio-shell.h */
+/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_shell_h_included
+#define __xio_shell_h_included 1
+
+extern const struct addrdesc xioaddr_shell;
+
+extern const struct optdesc opt_shell;
+
+#endif /* !defined(__xio_shell_h_included) */
diff --git a/xiohelp.c b/xiohelp.c
index 36edf7e..2e0b66b 100644
--- a/xiohelp.c
+++ b/xiohelp.c
@@ -43,7 +43,7 @@
 	"FD",		"FIFO",		"CHR",		"BLK",
 	"REG",		"SOCKET",	"READLINE",	"undef",
 	"NAMED",	"OPEN",		"EXEC",		"FORK",
-	"LISTEN",	"DEVICE",	"CHILD",	"RETRY",
+	"LISTEN",	"SHELL",	"CHILD",	"RETRY",
 	"TERMIOS",	"RANGE",	"PTY",		"PARENT",
 	"UNIX",		"IP4",		"IP6",		"INTERFACE",
 	"UDP",		"TCP",		"SOCKS4",	"OPENSSL",
diff --git a/xiomodes.h b/xiomodes.h
index 971a9a7..68b6fbd 100644
--- a/xiomodes.h
+++ b/xiomodes.h
@@ -41,6 +41,7 @@
 #include "xio-progcall.h"
 #include "xio-exec.h"
 #include "xio-system.h"
+#include "xio-shell.h"
 #include "xio-termios.h"
 #include "xio-readline.h"
 #include "xio-pty.h"
diff --git a/xioopen.c b/xioopen.c
index 110aef3..ca7e4d1 100644
--- a/xioopen.c
+++ b/xioopen.c
@@ -194,6 +194,9 @@
 #if WITH_GENERICSOCKET
    { "SENDTO",			&xioaddr_socket_sendto },
 #endif
+#if WITH_SHELL
+   { "SHELL",			&xioaddr_shell },
+#endif
 #if WITH_GENERICSOCKET
    { "SOCKET-CONNECT",		&xioaddr_socket_connect },
    { "SOCKET-DATAGRAM",		&xioaddr_socket_datagram },
diff --git a/xioopts.c b/xioopts.c
index a751ee4..ef8db90 100644
--- a/xioopts.c
+++ b/xioopts.c
@@ -1518,6 +1518,9 @@
 	IF_SOCKET ("setsockopt-string",	&opt_setsockopt_string)
 	IF_ANY    ("setuid",	&opt_setuid)
 	IF_ANY    ("setuid-early",	&opt_setuid_early)
+#if WITH_SHELL
+	IF_ANY	  ("shell", 		&opt_shell)
+#endif
 	IF_ANY    ("shut-close",	&opt_shut_close)
 	IF_ANY    ("shut-down",	&opt_shut_down)
 	IF_ANY    ("shut-none",	&opt_shut_none)
diff --git a/xioopts.h b/xioopts.h
index 99a0708..496b088 100644
--- a/xioopts.h
+++ b/xioopts.h
@@ -163,7 +163,7 @@
 #define GROUP_FORK	0x00000800	/* communication with forked process */
 
 #define GROUP_LISTEN	0x00001000	/* socket in listening mode */
-/*	0x00002000 */
+#define GROUP_SHELL	0x00002000
 #define GROUP_CHILD	0x00004000	/* autonom child process */
 #define GROUP_RETRY	0x00008000	/* when open/connect etc. fails */
 #define GROUP_TERMIOS	0x00010000
@@ -655,6 +655,7 @@
    OPT_SETUID,
    OPT_SETUID_EARLY,
    OPT_SET_NETNS, 	/* set net namespace */
+   OPT_SHELL,
    OPT_SHUT_CLOSE,
    OPT_SHUT_DOWN,
    OPT_SHUT_NONE,
diff --git a/xiosignal.c b/xiosignal.c
index 36d0595..6fe1e3b 100644
--- a/xiosignal.c
+++ b/xiosignal.c
@@ -55,7 +55,7 @@
 
    _errno = errno;
    diag_in_handler = 1;
-   Notice1("socatsignalpass(%d)", sig);
+   Notice1("socatsignalpass(sig=%d)", sig);
    if ((sigdesc = socat_get_sig_desc(sig)) == NULL) {	/* is async-signal-safe */
       diag_in_handler = 0;
       errno = _errno;
@@ -73,7 +73,8 @@
 	 }
       }
    }
-   Info1("socatsignalpass(): n=%d", n);
+   if (n >= 0)
+      Info1("socatsignalpass(): propagated signal to %d sub processes", n);
   }
 #if !HAVE_SIGACTION
    Signal(sig, socatsignalpass);