New option f-setpipe-sz
diff --git a/CHANGES b/CHANGES
index 6428d60..f1b79b6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -161,6 +161,11 @@
 	ABSTRACT_RECVFROM_CLIENT_BIND_TEMPNAME ABSTRACT_RECVFROM_SENDTO_BIND_TEMPNAME
 	Thanks to Kai Lüke for sending an initial patch.
 
+	New option f-setpipe-sz (pipesz) sets the pipe size on systems that
+	provide ioctl F_SETIPE_SZ.
+	Filan prints the current value.
+	Tests: STDIN_F_SETPIPE_SZ EXEC_F_SETPIPE_SZ
+
 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/VERSION b/VERSION
index ceaf471..77adf6d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-"1.7.4.5+"
+"1.7.4.5+setpipe"
diff --git a/doc/socat.yo b/doc/socat.yo
index 4746418..e00741d 100644
--- a/doc/socat.yo
+++ b/doc/socat.yo
@@ -1984,6 +1984,21 @@
 startdit()enddit()nl()
 
 
+label(GROUP_PIPE)em(bf(PIPE options))
+
+These options may be applied to pipes (fifos).
+
+startdit()
+label(OPTION_F_SETPIPE_SZ)dit(bf(tt(f-setpipe-sz=<int>)))
+dit(bf(tt(setpipe=<int>)))
+   Set the number of bytes a pipe can buffer. Where more bytes are written the
+   writing process might block. When more bytes are written in a single
+   tt(write()) the writing process blocks and might never recover.
+enddit()
+
+startdit()enddit()nl()
+
+
 label(GROUP_ADDRS)em(bf(General address options))
 
 These options may be applied to all address types. They change some process
diff --git a/filan.c b/filan.c
index 26f4668..36def50 100644
--- a/filan.c
+++ b/filan.c
@@ -146,10 +146,10 @@
 	    ;
 #if HAVE_POLL
 	 if (Poll(&ufds, 1, 0) < 0) {
-	    Warn4("poll({%d, %hd, %hd}, 1, 0): %s",
+	    Warn4("\tpoll({%d, %hd, %hd}, 1, 0): %s",
 		   ufds.fd, ufds.events, ufds.revents, strerror(errno));
 	 } else {
-	    fputs("poll: ", outfile);
+	    fputs("\tpoll: ", outfile);
 	    if (ufds.revents & POLLIN)   fputs("IN,", outfile);
 	    if (ufds.revents & POLLPRI)  fputs("PRI,", outfile);
 	    if (ufds.revents & POLLOUT)  fputs("OUT,", outfile);
@@ -378,6 +378,9 @@
   if (statfd >= 0) { /*!indent */
    switch (buf->st_mode&S_IFMT) {
    case (S_IFIFO):	/* 1, FIFO */
+#if defined(F_GETPIPE_SZ)
+      fprintf(outfile, "\tF_GETPIPE_SZ=%d", Fcntl(statfd, F_GETPIPE_SZ));
+#endif
       break;
    case (S_IFCHR):	/* 2, character device */
       cdevan(statfd, outfile);
diff --git a/sycls.c b/sycls.c
index 444d6ac..900cee3 100644
--- a/sycls.c
+++ b/sycls.c
@@ -574,6 +574,7 @@
    return result;
 }
 
+/* fcntl() without value */
 int Fcntl(int fd, int cmd) {
    int result, _errno;
    if (!diag_in_handler) diag_flush();
@@ -581,7 +582,8 @@
    Debug2("fcntl(%d, %d)", fd, cmd);
 #endif /* WITH_SYCLS */
    result = fcntl(fd, cmd);
-   if (!diag_in_handler) diag_flush();
+   if (!diag_in_handler)
+      diag_flush();
 #if WITH_SYCLS
    _errno = errno;
    Debug1("fcntl() -> 0x%x", result);
@@ -590,6 +592,25 @@
    return result;
 }
 
+/* fcntl() with int value */
+int Fcntl_i(int fd, int cmd, int arg) {
+   int result, _errno;
+   if (!diag_in_handler) diag_flush();
+#if WITH_SYCLS
+   Debug3("fcntl(%d, %d, 0x%x)", fd, cmd, arg);
+#endif /* WITH_SYCLS */
+   result = fcntl(fd, cmd, arg);
+   _errno = errno;
+   if (!diag_in_handler)
+      diag_flush();
+#if WITH_SYCLS
+   Debug1("fcntl() -> 0x%x", result);
+#endif /* WITH_SYCLS */
+   errno = _errno;
+   return result;
+}
+
+/* fcntl() with long value */
 int Fcntl_l(int fd, int cmd, long arg) {
    int result, _errno;
    if (!diag_in_handler) diag_flush();
@@ -598,7 +619,8 @@
 #endif /* WITH_SYCLS */
    result = fcntl(fd, cmd, arg);
    _errno = errno;
-   if (!diag_in_handler) diag_flush();
+   if (!diag_in_handler)
+      diag_flush();
 #if WITH_SYCLS
    Debug1("fcntl() -> 0x%x", result);
 #endif /* WITH_SYCLS */
diff --git a/sycls.h b/sycls.h
index 6b64d27..8f8ded5 100644
--- a/sycls.h
+++ b/sycls.h
@@ -61,6 +61,7 @@
 ssize_t Read(int fd, void *buf, size_t count);
 ssize_t Write(int fd, const void *buf, size_t count);
 int Fcntl(int fd, int cmd);
+int Fcntl_i(int fd, int cmd, int arg);
 int Fcntl_l(int fd, int cmd, long arg);
 int Fcntl_lock(int fd, int cmd, struct flock *l);
 #if WITH_SYCLS
diff --git a/sysutils.c b/sysutils.c
index 24efd39..c62d555 100644
--- a/sysutils.c
+++ b/sysutils.c
@@ -44,7 +44,7 @@
 	 default: return -1;
 	 }
       } else if (writt+chk < bytes) {
-	 Warn4("write(%d, %p, "F_Zu"): only wrote "F_Zu" bytes, trying to continue ",
+	 Warn4("write(%d, %p, "F_Zu"): only wrote "F_Zu" bytes, trying to continue (rev.direction is blocked)",
 	       fd, (const char *)buff+writt, bytes-writt, chk);
 	 writt += chk;
       } else {
@@ -52,6 +52,7 @@
 	 break;
       }
    }
+   Notice3("write(%d, %p, "F_Zu") completed", fd, (const char *)buff, bytes);
    return writt;
 }
 
diff --git a/test.sh b/test.sh
index 0768db6..84f5909 100755
--- a/test.sh
+++ b/test.sh
@@ -7652,25 +7652,27 @@
 sleep 1
 # read from the first file
 sh -c "$CMD" 2>"$te"
-if [ $? -ne 0 ]; then # command failed
-    $PRINTF "${FAILED}:\n"
+rc=$?
+if [ $rc -ne 0 ]; then # command failed
+    $PRINTF "${FAILED} (rc=$rc):\n"
     echo "$CMD"
-    cat "$te"
+    cat "$te" >&2
     numFAIL=$((numFAIL+1))
     listFAIL="$listFAIL $N"
 else
 # check which file has a later atime stamp
 if [ $(ls -ltu "${tf}1" "${tf}2" |head -1 |sed 's/.* //') != "${tf}2" ];
 then
-   $PRINTF "$FAILED: $TRACE $SOCAT:\n"
-   echo "$CMD"
-   cat "$te"
+    $PRINTF "$FAILED (bad order):\n"
+    echo "$CMD" >&2
+    cat "$te"
     numFAIL=$((numFAIL+1))
     listFAIL="$listFAIL $N"
 else
-   $PRINTF "$OK\n"
-   if [ -n "$debug" ]; then cat "$te"; fi
-   numOK=$((numOK+1))
+    $PRINTF "$OK\n"
+    if [ "$VERBOSE" ]; then echo "$CMD"; fi
+    if [ "$DEBUG" ];   then cat "${te}" >&2; fi
+    numOK=$((numOK+1))
 fi # wrong time stamps
 fi # command ok
 fi ;; # NUMCOND, feats
@@ -17998,6 +18000,133 @@
 N=$((N+1))
 
 
+# Test the new f-setpipe-sz option on a STDIN pipe
+NAME=STDIN_F_SETPIPE_SZ
+case "$TESTS" in
+*%$N%*|*%functions%*|*%filan%*|*%dual%*|*%stdio%*|*%exec%*|*%pipe%*|*%f-setpipe-sz%*|*%$NAME%*)
+TEST="$NAME: f-setpipe-sz on STDIN"
+# Start Socat in a shell pipe and have it calling Filan via EXEC and nofork
+# Check Filan output if pipe size of its input pipe is modified.
+if ! eval $NUMCOND; then :;
+# Remove unneeded checks, adapt lists of the remaining ones
+elif ! $(type true >/dev/null 2>&1); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}true not available${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! F=$(testfeats STDIO EXEC); 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); 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 f-setpipe-sz nofork) >/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"
+newport tcp4 	# or whatever proto, or drop this line
+# Find the default pipe size
+PIPESZ="$(echo |$FILAN -n 0 |grep "0:" |head -n 1 |sed 's/.*F_GETPIPE_SZ=\([0-9][0-9]*\).*/\1/')"
+PIPESZ2=$((2*PIPESZ))
+CMD0="$TRACE $SOCAT $opts STDIN,f-setpipe-sz=$PIPESZ2!!STDOUT EXEC:$FILAN,nofork"
+printf "test $F_n $TEST... " $N
+true |$CMD0 >"${tf}" 2>"${te}0"
+rc0=$?
+PIPESZ2b="$(cat "$tf" |grep "0:" |head -n 1 |sed 's/.*F_GETPIPE_SZ=\([0-9][0-9]*\).*/\1/')"
+if [ "$rc0" -ne 0 ]; then
+    $PRINTF "$FAILED\n"
+    echo "$CMD0"
+    cat "${te}0" >&2
+    numFAIL=$((numFAIL+1))
+    listFAIL="$listFAIL $N"
+    namesFAIL="$namesFAIL $NAME"
+elif ! diff <(echo $PIPESZ2) <(echo $PIPESZ2b) >$tdiff; then
+    $PRINTF "$FAILED\n"
+    echo "$CMD0"
+    cat "${te}0" >&2
+    echo "diff:" >&2
+    cat "$tdiff" >&2
+    numFAIL=$((numFAIL+1))
+    listFAIL="$listFAIL $N"
+    namesFAIL="$namesFAIL $NAME"
+else
+    $PRINTF "$OK\n"
+    if [ "$VERBOSE" ]; then echo "$CMD0"; fi
+    if [ "$DEBUG" ];   then cat "${te}0" >&2; fi
+    numOK=$((numOK+1))
+fi
+fi # NUMCOND
+ ;;
+esac
+N=$((N+1))
+
+# Test the new f-setpipe-sz option on EXEC with pipes
+NAME=EXEC_F_SETPIPE_SZ
+case "$TESTS" in
+*%$N%*|*%functions%*|*%filan%*|*%stdio%*|*%exec%*|*%pipe%*|*%f-setpipe-sz%*|*%$NAME%*)
+TEST="$NAME: f-setpipe-sz on EXEC with pipes"
+# Start Socat calling Filan via EXEC and pipes and f-setpipe-sz
+# Check Filan output if pipe size of both pipes is modified.
+if ! eval $NUMCOND; then :;
+# Remove unneeded checks, adapt lists of the remaining ones
+elif ! F=$(testfeats STDIO EXEC); 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); 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 pipes f-setpipe-sz) >/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"
+# Find the default pipe size
+PIPESZ="$(echo |$FILAN -n 0 |grep "0:" |head -n 1 |sed 's/.*F_GETPIPE_SZ=\([0-9][0-9]*\).*/\1/')"
+PIPESZ2=$((2*PIPESZ))
+CMD0="$TRACE $SOCAT $opts STDIO EXEC:$FILAN,pipes,f-setpipe-sz=$PIPESZ2"
+printf "test $F_n $TEST... " $N
+$CMD0 >"$tf" 2>"${te}0"
+rc0=$?
+PIPESZ2b="$(cat "$tf" |grep "0:" |head -n 1 |sed 's/.*F_GETPIPE_SZ=\([0-9][0-9]*\).*/\1/')"
+if [ "$rc0" -ne 0 ]; then
+    $PRINTF "$FAILED\n"
+    echo "$CMD0"
+    cat "${te}0" >&2
+    numFAIL=$((numFAIL+1))
+    listFAIL="$listFAIL $N"
+    namesFAIL="$namesFAIL $NAME"
+elif ! diff <(echo $PIPESZ2) <(echo $PIPESZ2b) >$tdiff; then
+    $PRINTF "$FAILED\n"
+    echo "$CMD0 &"
+    cat "${te}0" >&2
+    echo "diff:" >&2
+    cat "$tdiff" >&2
+    numFAIL=$((numFAIL+1))
+    listFAIL="$listFAIL $N"
+    namesFAIL="$namesFAIL $NAME"
+else
+    $PRINTF "$OK\n"
+    if [ "$VERBOSE" ]; then echo "$CMD0"; fi
+    if [ "$DEBUG" ];   then cat "${te}0" >&2; fi
+    numOK=$((numOK+1))
+fi
+fi # NUMCOND
+ ;;
+esac
+N=$((N+1))
+
+
 # end of common tests
 
 ##################################################################################
diff --git a/xio-pipe.c b/xio-pipe.c
index 7d260c1..718333f 100644
--- a/xio-pipe.c
+++ b/xio-pipe.c
@@ -20,6 +20,9 @@
 
 const struct addrdesc xioaddr_pipe   = { "PIPE",   3, xioopen_fifo,  GROUP_FD|GROUP_NAMED|GROUP_OPEN|GROUP_FIFO, 0, 0, 0 HELP("[:<filename>]") };
 
+#if defined(F_SETPIPE_SZ)
+const struct optdesc opt_f_setpipe_sz = { "f-setpipe-sz", "pipesz", OPT_F_SETPIPE_SZ, GROUP_FD, PH_FD, TYPE_INT, OFUNC_FCNTL, F_SETPIPE_SZ, 0 };
+#endif
 
 /* process an unnamed bidirectional "pipe" or "fifo" or "echo" argument with
    options */
diff --git a/xio-pipe.h b/xio-pipe.h
index 1ea8ba9..7171e6b 100644
--- a/xio-pipe.h
+++ b/xio-pipe.h
@@ -7,4 +7,6 @@
 
 extern const struct addrdesc xioaddr_pipe;
 
+extern const struct optdesc opt_f_setpipe_sz;
+
 #endif /* !defined(__xio_pipe_h_included) */
diff --git a/xio-progcall.c b/xio-progcall.c
index 5cbd505..5a0f54d 100644
--- a/xio-progcall.c
+++ b/xio-progcall.c
@@ -291,6 +291,7 @@
 
    if (usepipes) {
       /* withfork usepipes */
+      struct opt *popts2 = NULL;
 
       if (rw == XIO_RDWR)
 	 sfd->dtype = XIODATA_2PIPE;
@@ -309,6 +310,8 @@
 	 return -1;
       }
       popts = opts;
+      if (sfd->dtype == XIODATA_2PIPE)
+	 popts2 = copyopts(popts, GROUP_ALL);
 
       if (rw != XIO_WRONLY) {
 	 applyopts_cloexec(rdpip[0], popts);
@@ -326,8 +329,11 @@
       /* wrpip[1]: write by socat; wrpip[0]: read by child */
       if (rw != XIO_RDONLY) {
 	 applyopts_cloexec(wrpip[1], popts);
-	 applyopts(sfd, wrpip[1], popts, PH_FD);
-	 applyopts(sfd, wrpip[0], copts, PH_FD);
+	 if (sfd->dtype == XIODATA_2PIPE)
+	    applyopts(NULL, wrpip[1], popts, PH_FD);
+	 else
+	    applyopts(NULL, wrpip[1], popts, PH_FD);
+	 applyopts(NULL, wrpip[0], copts, PH_FD);
       }
       if (sfd->howtoend == END_UNSPEC) {
 	 sfd->howtoend = END_CLOSE_KILL;
diff --git a/xioopts.c b/xioopts.c
index 679fc6d..a428586 100644
--- a/xioopts.c
+++ b/xioopts.c
@@ -548,6 +548,9 @@
 	IF_ANY 	  ("f-setlkw",	&opt_f_setlkw_wr)
 	IF_ANY 	  ("f-setlkw-rd",	&opt_f_setlkw_rd)
 	IF_ANY 	  ("f-setlkw-wr",	&opt_f_setlkw_wr)
+#if defined(F_SETPIPE_SZ)
+	IF_ANY    ("f-setpipe-sz",	&opt_f_setpipe_sz)
+#endif
 	IF_EXEC   ("fdin",	&opt_fdin)
 	IF_EXEC   ("fdout",	&opt_fdout)
 #ifdef FFDLY
@@ -1305,6 +1308,9 @@
 	IF_SOCKET ("pf",	&opt_protocol_family)
 	IF_EXEC   ("pgid",	&opt_setpgid)
 	IF_EXEC   ("pipes",	&opt_pipes)
+#if defined(F_SETPIPE_SZ)
+	IF_ANY    ("pipesz",	&opt_f_setpipe_sz)
+#endif
 #ifdef IP_PKTINFO
 	IF_IP     ("pktinfo",	&opt_ip_pktinfo)
 #endif
@@ -3375,23 +3381,34 @@
 {
 	int flag;
 
-	/* retrieve existing flag setttings */
-	if ((flag = Fcntl(fd, opt->desc->major-1)) < 0) {
+	if (opt->desc->type == TYPE_BOOL) {
+	   /* Retrieve existing flag settings */
+	   if ((flag = Fcntl(fd, opt->desc->major-1)) < 0) {
 		Error3("fcntl(%d, %d): %s",
 		       fd, opt->desc->major, strerror(errno));
 		return -1;
+	   }
+	   if (opt->value.u_bool) {
+	      flag |= opt->desc->minor;
+	   } else {
+	      flag &= ~opt->desc->minor;
+	   }
+	   if (Fcntl_i(fd, opt->desc->major, flag) < 0) {
+	      Error4("fcntl(%d, %d, 0x%x): %s",
+		     fd, opt->desc->major, flag, strerror(errno));
+	      return -1;
+	   }
+
+	} else if (opt->desc->type == TYPE_INT) {
+	   if (Fcntl_i(fd, opt->desc->major, opt->value.u_int) < 0) {
+	      Error4("fcntl(%d, %d, 0x%x): %s",
+		     fd, opt->desc->major, opt->value.u_int, strerror(errno));
+	      return -1;
+	   }
 	} else {
-		if (opt->value.u_bool) {
-			flag |= opt->desc->minor;
-		} else {
-			flag &= ~opt->desc->minor;
-		}
-		if (Fcntl_l(fd, opt->desc->major, flag) < 0) {
-			Error4("fcntl(%d, %d, %d): %s",
-			       fd, opt->desc->major, flag,
-			       strerror(errno));
-			return -1;
-		}
+	   Error2("applyopt_fcntl(\"%s\", ...): INTERNAL: type %d not implemented",
+		  opt->desc->defname, opt->desc->type);
+	   return -1;
 	}
 	return 0;
 }
diff --git a/xioopts.h b/xioopts.h
index 0ed8881..f0f9894 100644
--- a/xioopts.h
+++ b/xioopts.h
@@ -351,6 +351,7 @@
    OPT_F_SETLKW_WR,	/* fcntl with struct flock - write-lock, wait */
    OPT_F_SETLK_RD,	/* fcntl with struct flock - read-lock */
    OPT_F_SETLK_WR,	/* fcntl with struct flock - write-lock */
+   OPT_F_SETPIPE_SZ, 	/* pipe == fifo */
    OPT_GROUP,
    OPT_GROUP_EARLY,
    OPT_GROUP_LATE,
diff --git a/xiowrite.c b/xiowrite.c
index 1619bc4..5388baf 100644
--- a/xiowrite.c
+++ b/xiowrite.c
@@ -96,12 +96,11 @@
       }
       if ((size_t)writt < bytes) {
 	 char infobuff[256];
-	 Warn7("sendto(%d, %p, "F_Zu", 0, %s, "F_socklen") only wrote "F_Zu" of "F_Zu" bytes",
+	 Warn7("sendto(%d, %p, "F_Zu", 0, %s, "F_socklen") only sent "F_Zu" of "F_Zu" bytes",
 	       pipe->fd, buff, bytes,
 	       sockaddr_info(&pipe->peersa.soa, pipe->salen,
 			     infobuff, sizeof(infobuff)),
 	       pipe->salen, writt, bytes);
-      } else {
       }
       {
 	 char infobuff[256];