-r, -R now with CLOEXEC, and warn on write problems
diff --git a/CHANGES b/CHANGES
index 1594fb8..dd5d667 100644
--- a/CHANGES
+++ b/CHANGES
@@ -74,6 +74,13 @@
 
 	fcntl() trace prints flags now in hexadecimal.
 
+	Stream dump options -r and -R now open their pathes with CLOEXEC to
+	prevent leaking into sub processes.
+	Test: EXEC_SNIFF
+
+	Stream dump write now warn on write errors and partial writes (but
+	still do not recover).
+
 Porting:
 	Small correction in configure.ac makes Socat C99 able.
 	Thanks to Florian Weimer from Red Hat for providing a patch.
diff --git a/socat.c b/socat.c
index b2600b4..f65fe75 100644
--- a/socat.c
+++ b/socat.c
@@ -59,6 +59,7 @@
 void socat_usage(FILE *fd);
 void socat_opt_hint(FILE *fd, char a, char b);
 void socat_version(FILE *fd);
+static int xio_openauxwr(const char *path, const char *hint);
 int socat(const char *address1, const char *address2);
 int _socat(void);
 int cv_newline(unsigned char *buff, ssize_t *bytes, int lineterm1, int lineterm2);
@@ -187,21 +188,9 @@
 	       break;
 	    }
 	 }
-	 if ((socat_opts.sniffleft = Open(a, O_CREAT|O_WRONLY|O_APPEND|
-#ifdef O_LARGEFILE
-					  O_LARGEFILE|
-#endif
-					  O_NONBLOCK, 0664)) < 0) {
-	    if (errno == ENXIO) {
-	       if ((socat_opts.sniffleft = Open(a, O_CREAT|O_RDWR|O_APPEND|
-#ifdef O_LARGEFILE
-						O_LARGEFILE|
-#endif
-						O_NONBLOCK, 0664)) > 0)
-		  break; 	/* try to open pipe rdwr */
-	    }
-	    Error2("option -r \"%s\": %s", a, strerror(errno));
-         }
+	 if ((socat_opts.sniffleft = xio_openauxwr(a, "option -r")) < 0) {
+	    Error2("option -r: failed to open \"%s\": %s", a, strerror(errno));
+	 }
 	 break;
       case 'R': if (arg1[0][2]) {
 	    a = *arg1+2;
@@ -212,21 +201,9 @@
 	       break;
 	    }
 	 }
-	 if ((socat_opts.sniffright = Open(a, O_CREAT|O_WRONLY|O_APPEND|
-#ifdef O_LARGEFILE
-					   O_LARGEFILE|
-#endif
-					   O_NONBLOCK, 0664)) < 0) {
-	    if (errno == ENXIO) {
-	       if ((socat_opts.sniffright = Open(a, O_CREAT|O_RDWR|O_APPEND|
-#ifdef O_LARGEFILE
-						O_LARGEFILE|
-#endif
-						O_NONBLOCK, 0664)) > 0)
-		  break; 	/* try to open pipe rdwr */
-	    }
-	    Error2("option -R \"%s\": %s", a, strerror(errno));
-         }
+	 if ((socat_opts.sniffright = xio_openauxwr(a, "option -R")) < 0) {
+	    Error2("option -R: failed to open \"%s\": %s", a, strerror(errno));
+	 }
 	 break;
       case 'b': if (arg1[0][2]) {
 	    a = *arg1+2;
@@ -629,6 +606,47 @@
 }
 
 
+/* Opens a path for logging or tracing.
+   Return the filedescriptor, or -1 when an error occurred (errn0).
+   Prints messages but no Error().
+*/
+static int xio_openauxwr(const char *path, const char *hint)
+{
+	int fd;
+	int _errno;
+
+	if ((fd = Open(path, O_CREAT|O_WRONLY|O_APPEND|
+#ifdef O_LARGEFILE
+		       O_LARGEFILE|
+#endif
+#ifdef O_CLOEXEC
+		       O_CLOEXEC|
+#endif
+		       O_NONBLOCK, 0664)) < 0) {
+		if (errno != ENXIO)
+			return -1;
+		/* Possibly a named pipe that does not yet have a reader */
+		_errno = errno;
+		Notice3("%s \"%s\": %s, retrying r/w", hint, path, strerror(errno));
+		if ((fd = Open(path, O_CREAT|O_RDWR|O_APPEND|
+#ifdef O_LARGEFILE
+			       O_LARGEFILE|
+#endif
+#ifdef O_CLOEXEC
+			       O_CLOEXEC|
+#endif
+			       O_NONBLOCK, 0664)) < 0) {
+			errno = _errno;
+			return -1;
+		}
+	}
+#ifndef O_CLOEXEC
+	 Fcntl_l(fd, F_SETFD, FD_CLOEXEC);
+#endif
+	 return fd;
+}
+
+
 xiofile_t *sock1, *sock2;
 int closing = 0;	/* 0..no eof yet, 1..first eof just occurred,
 			   2..counting down closing timeout */
@@ -1281,6 +1299,7 @@
 int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
 		unsigned char *buff, size_t bufsiz, bool righttoleft) {
    ssize_t bytes, writt = 0;
+   ssize_t sniffed;
 
 	 bytes = xioread(inpipe, buff, bufsiz);
 	 if (bytes < 0) {
@@ -1331,9 +1350,23 @@
 	    }
 
 	    if (!righttoleft && socat_opts.sniffleft >= 0) {
-	       Write(socat_opts.sniffleft, buff, bytes);
+	       if ((sniffed = Write(socat_opts.sniffleft, buff, bytes)) < bytes) {
+		  if (sniffed < 0)
+		     Warn3("-r: write(%d, buff, "F_Zu"): %s",
+			   socat_opts.sniffleft, bytes, strerror(errno));
+		  else if (sniffed < bytes)
+		     Warn3("-r: write(%d, buff, "F_Zu") -> "F_Zd,
+			   socat_opts.sniffleft, bytes, sniffed);
+	       }
 	    } else if (righttoleft && socat_opts.sniffright >= 0) {
-	       Write(socat_opts.sniffright, buff, bytes);
+	       if ((sniffed = Write(socat_opts.sniffright, buff, bytes)) < bytes) {
+		  if (sniffed < 0)
+		     Warn3("-R: write(%d, buff, "F_Zu"): %s",
+			   socat_opts.sniffright, bytes, strerror(errno));
+		  else if (sniffed < bytes)
+		     Warn3("-R: write(%d, buff, "F_Zu") -> "F_Zd,
+			   socat_opts.sniffright, bytes, sniffed);
+	       }
 	    }
 
 	    if (socat_opts.verbose && socat_opts.verbhex) {
diff --git a/test.sh b/test.sh
index 6c413d1..f778bd5 100755
--- a/test.sh
+++ b/test.sh
@@ -15963,7 +15963,16 @@
 TEST="$NAME: Socat does not leak FDs to EXEC'd program"
 # Run Socat with EXEC address, execute Filan to display its file descriptors
 # Test succeeds when only FDs 0, 1, 2 are in use.
-if ! eval $NUMCOND; then :; else
+if ! eval $NUMCOND; then :;
+elif ! a=$(testaddrs STDIO EXEC); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Address $a not available${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! o=$(testoptions stderr) >/dev/null; then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available${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"
@@ -15974,15 +15983,60 @@
 # "door" is a special FD type on Solaris/SunOS
 if [ "$(cat  "${tf}" |grep -v ' door ' |wc -l)" -eq 3 ]; then
     $PRINTF "$OK\n"
-    if [ "$VERBOSE" ]; then
-	echo "$CMD" >&2
-    fi
+    if [ "$VERBOSE" ]; then echo "$CMD"; fi
+    if [ "$DEBUG" ];   then cat "${te}" >&2; fi
     numOK=$((numOK+1))
 else
     $PRINTF "$FAILED\n"
     echo "$CMD" >&2
-    cat "${tf}" >&2
     cat "${te}" >&2
+    cat "${tf}" >&2
+    numFAIL=$((numFAIL+1))
+    listFAIL="$listFAIL $N"
+fi
+fi # NUMCOND
+ ;;
+esac
+PORT=$((PORT+1))
+N=$((N+1))
+
+# Test if Socat makes the sniffing file descriptos (-r, -R) CLOEXEC to not leak
+# them to EXEC'd program
+NAME=EXEC_SNIFF
+case "$TESTS" in
+*%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%filan%*|*%$NAME%*)
+TEST="$NAME: Socat does not leak sniffing FDs"
+# Run Socat sniffing both directions, with EXEC address,
+# execute Filan to display its file descriptors
+# Test succeeds when only FDs 0, 1, 2 are in use.
+if ! eval $NUMCOND; then :;
+elif ! a=$(testaddrs STDIO EXEC); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Address $a not available${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! o=$(testoptions stderr) >/dev/null; then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available${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"
+CMD="$TRACE $SOCAT $opts -r $td/test$N.-r -R $td/test$N.-R  - EXEC:\"$FILAN -s\",stderr"
+printf "test $F_n $TEST... " $N
+eval "$CMD" >"${tf}" 2>"${te}"
+# "door" is a special FD type on Solaris/SunOS
+if [ "$(cat  "${tf}" |grep -v ' door ' |wc -l)" -eq 3 ]; then
+    $PRINTF "$OK\n"
+    if [ "$VERBOSE" ]; then echo "$CMD"; fi
+    if [ "$DEBUG" ];   then cat "${te}" >&2; fi
+    numOK=$((numOK+1))
+else
+    $PRINTF "$FAILED\n"
+    echo "$CMD" >&2
+    cat "${te}" >&2
+    cat "${tf}" >&2
     numFAIL=$((numFAIL+1))
     listFAIL="$listFAIL $N"
 fi