New address SOCKETPAIR for echoing datagrams
diff --git a/CHANGES b/CHANGES
index 10e5c00..3996481 100644
--- a/CHANGES
+++ b/CHANGES
@@ -13,6 +13,12 @@
 	The number of warnings has been reduced, e.g.removing a non existing
 	file does in most cases no longer log a warning.
 
+	Added address type internal SOCKETPAIR. This is similar to the unnamed
+	PIPE address (only for internal echoing) but it provides datagram mode
+	(the default) and thus keeps packet boundaries.
+	Tests: SOCKETPAIR_STREAM SOCKETPAIR_DATAGRAM SOCKETPAIR_SEQPACKET
+	SOCKETPAIR_BOUNDARIES
+
 	New option -S <mask> controls catching and logging of signals that are
 	not internally used by Socat.
 	Tests: SIGTERM_NOLOG SIG31_LOG
diff --git a/Makefile.in b/Makefile.in
index a54a954..95fcca9 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -45,7 +45,7 @@
 	xiosignal.c xiosigchld.c xioread.c xiowrite.c \
 	xiolayer.c xioshutdown.c xioclose.c xioexit.c \
 	xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \
-	xio-gopen.c xio-creat.c xio-file.c xio-named.c \
+	xio-socketpair.c xio-gopen.c xio-creat.c xio-file.c xio-named.c \
 	xio-socket.c xio-interface.c xio-listen.c xio-unix.c xio-vsock.c \
 	xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \
 	xio-sctp.c xio-rawip.c \
@@ -64,7 +64,7 @@
 	xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.h \
 	xiomodes.h xiolayer.h xio-process.h xio-fd.h xio-fdnum.h xio-stdio.h \
 	xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h \
-	xio-socket.h xio-interface.h xio-listen.h xio-unix.h xio-vsock.h \
+	xio-socketpair.h xio-socket.h xio-interface.h xio-listen.h xio-unix.h xio-vsock.h \
 	xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \
 	xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \
 	xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \
diff --git a/config.h.in b/config.h.in
index a87bf21..67e566c 100644
--- a/config.h.in
+++ b/config.h.in
@@ -692,6 +692,7 @@
 #undef WITH_GOPEN
 #undef WITH_TERMIOS
 #undef WITH_PIPE
+#undef WITH_SOCKETPAIR
 #undef WITH_UNIX
 #undef WITH_ABSTRACT_UNIXSOCKET
 #undef WITH_IP4
diff --git a/configure.ac b/configure.ac
index bf04260..7dced77 100644
--- a/configure.ac
+++ b/configure.ac
@@ -219,6 +219,14 @@
 	       esac],
 	       [AC_DEFINE(WITH_PIPE) AC_MSG_RESULT(yes)])
 
+AC_MSG_CHECKING(whether to include explicit socketpair support)
+AC_ARG_ENABLE(socketpair, [  --disable-socketpair    disable socketpair support],
+	      [case "$enableval" in
+	       no) AC_MSG_RESULT(no);;
+	       *) AC_DEFINE(WITH_SOCKETPAIR) AC_MSG_RESULT(yes);;
+	       esac],
+	       [AC_DEFINE(WITH_SOCKETPAIR) AC_MSG_RESULT(yes)])
+
 AC_MSG_CHECKING(whether to include explicit termios support)
 AC_ARG_ENABLE(termios, [  --disable-termios       disable termios support],
 	      [case "$enableval" in
diff --git a/doc/socat.yo b/doc/socat.yo
index b28e55f..114d82f 100644
--- a/doc/socat.yo
+++ b/doc/socat.yo
@@ -682,13 +682,22 @@
    See also: link(unnamed pipe)(ADDRESS_UNNAMED_PIPE)
 label(ADDRESS_UNNAMED_PIPE)dit(bf(tt(PIPE)))
    Creates an unnamed pipe and uses it for reading and writing. It works as an
-   echo, because everything written 
-   to it appeares immediately as read data.nl()
+   echo, because everything written to it appeares immediately as read
+   data.nl()
    Note: When socat tries to write more bytes than the pipe can queue (Linux
    2.4: 2048 bytes), socat might block. Consider, e.g., using
    option code(-b 2048) nl()
    Option groups: link(FD)(GROUP_FD) nl()
-   See also: link(named pipe)(ADDRESS_NAMED_PIPE)
+   See also: link(named pipe)(ADDRESS_NAMED_PIPE), link(SOCKETPAIR)(ADDRESS_SOCKETPAIR)
+label(ADDRESS_SOCKETPAIR)dit(bf(tt(SOCKETPAIR)))
+   Creates a socketpair and uses it for reading and writing. It works as an
+   echo, because everything written to it appeares immediately as read
+   data. The default socket type is datagram, so it keeps packet boundaries.
+   nl()
+   Option groups: link(FD)(GROUP_FD) nl()
+   Useful options:
+   link(socktype)(OPTION_SO_TYPE)nl()
+   See also: link(unnamed pipe)(ADDRESS_UNNAMED_PIPE)
 label(ADDRESS_PROXY_CONNECT)dit(bf(tt(PROXY:<proxy>:<hostname>:<port>)))
    Connects to an HTTP proxy server on port 8080 using TCP/IP  version 4 or 6
    depending on address specification, name resolution, or option
diff --git a/socat.c b/socat.c
index 6f25707..e2b1bd8 100644
--- a/socat.c
+++ b/socat.c
@@ -540,6 +540,11 @@
 #else
    fputs("  #undef WITH_PIPE\n", fd);
 #endif
+#ifdef WITH_SOCKETPAIR
+   fprintf(fd, "  #define WITH_SOCKETPAIR %d\n", WITH_SOCKETPAIR);
+#else
+   fputs("  #undef WITH_SOCKETPAIR\n", fd);
+#endif
 #ifdef WITH_UNIX
    fprintf(fd, "  #define WITH_UNIX %d\n", WITH_UNIX);
 #else
diff --git a/test.sh b/test.sh
index 0fea81b..a52b78d 100755
--- a/test.sh
+++ b/test.sh
@@ -16546,6 +16546,108 @@
 N=$((N+1))
 
 
+NAME=SOCKETPAIR_STREAM
+case "$TESTS" in
+*%$N%*|*%functions%*|*%stdio%*|*%socketpair%*|*%$NAME%*)
+TEST="$NAME: stdio and internal socketpair with stream"
+testecho "$N" "$TEST" "STDIO" "SOCKETPAIR" "$opts"
+esac
+N=$((N+1))
+
+NAME=SOCKETPAIR_DATAGRAM
+case "$TESTS" in
+*%$N%*|*%functions%*|*%stdio%*|*%socketpair%*|*%$NAME%*)
+TEST="$NAME: stdio and internal socketpair with datagram"
+testecho "$N" "$TEST" "STDIO" "SOCKETPAIR,socktype=2" "$opts"
+esac
+N=$((N+1))
+
+NAME=SOCKETPAIR_SEQPACKET
+case "$TESTS" in
+*%$N%*|*%functions%*|*%stdio%*|*%socketpair%*|*%$NAME%*)
+TEST="$NAME: stdio and internal socketpair with seqpacket"
+testecho "$N" "$TEST" "STDIO" "SOCKETPAIR,socktype=$SOCK_SEQPACKET" "$opts"
+esac
+N=$((N+1))
+
+# Test if SOCKETPAIR address with SOCK_DGRAM keeps packet boundaries
+NAME=SOCKETPAIR_BOUNDARIES
+case "$TESTS" in
+*%$N%*|*%functions%*|*%socketpair%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%$NAME%*)
+TEST="$NAME: Internal socketpair keeps packet boundaries"
+# Start a UDP4-DATAGRAM process that echoes data with datagram SOCKETPAIR;
+# a client sends two packets with 24 and ~18 bytes using a UDP4-DATAGRAM. The
+# client truncates packets to size 24, so when a large merged packet comes from
+# server some data will be lost. If the original data is received, the test
+# succeeded.
+if ! eval $NUMCOND; then :;
+elif ! F=$(testfeats STDIO IP4 UDP SOCKETPAIR); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! A=$(testaddrs - STDIO UDP4-DATAGRAM SOCKETPAIR); 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 bind socktype ) >/dev/null; then
+    $PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available in $SOCAT${NORMAL}\n" $N
+    numCANT=$((numCANT+1))
+    listCANT="$listCANT $N"
+elif ! runsip4 >/dev/null; then
+    $PRINTF "test $F_n $TEST... ${YELLOW}IPv4 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"
+ts1p=$PORT; PORT=$((PORT+1))
+ts2p=$PORT; PORT=$((PORT+1))
+da="test$N $(date) $RANDOM"
+CMD1="$TRACE $SOCAT $opts -T 0.2 UDP4-DATAGRAM:$LOCALHOST:$ts2p,bind=$LOCALHOST:$ts1p SOCKETPAIR,socktype=$SOCK_DGRAM"
+CMD2="$TRACE $SOCAT $opts -b 24 -t 0.2 -T 0.3 - UDP4-DATAGRAM:$LOCALHOST:$ts1p,bind=$LOCALHOST:$ts2p"
+printf "test $F_n $TEST... " $N
+export SOCAT_TRANSFER_WAIT=0.2
+$CMD1 2>"${te}1" &
+pid1="$!"
+unset SOCAT_TRANSFER_WAIT
+waitudp4port $ts1p 1
+{ echo -n "${da:0:20}"; usleep 100000; echo "${da:20}"; } |$CMD2 >>"$tf" 2>>"${te}2"
+rc2="$?"
+kill "$pid1" 2>/dev/null; wait;
+if [ "$rc2" -ne 0 ]; then
+    $PRINTF "$FAILED (rc2=$rc2): $TRACE $SOCAT:\n"
+    echo "$CMD1 &"
+    cat "${te}1" >&2
+    echo "$CMD2"
+    cat "${te}2" >&2
+    numFAIL=$((numFAIL+1))
+    listFAIL="$listFAIL $N"
+elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
+    $PRINTF "$FAILED\n"
+    echo "$CMD1 &"
+    cat "${te}1" >&2
+    echo "$CMD2"
+    cat "${te}2" >&2
+    echo diff:
+    cat "$tdiff"
+    numFAIL=$((numFAIL+1))
+    listFAIL="$listFAIL $N"
+else
+    $PRINTF "$OK\n"
+    if [ "$VERBOSE" ]; then echo "$CMD1"; fi
+    if [ "$DEBUG" ];   then cat "${te}1" >&2; fi
+    if [ "$VERBOSE" ]; then echo "$CMD2 &"; fi
+    if [ "$DEBUG" ];   then cat "${te}2" >&2; fi
+    numOK=$((numOK+1))
+fi
+fi # NUMCOND
+ ;;
+esac
+PORT=$((PORT+1))
+N=$((N+1))
+
+
 # end of common tests
 
 ##################################################################################
diff --git a/xio-pipe.c b/xio-pipe.c
index c4c8ceb..5b7d077 100644
--- a/xio-pipe.c
+++ b/xio-pipe.c
@@ -9,6 +9,8 @@
 
 #include "xio-named.h"
 
+#include "xio-pipe.h"
+
 
 #if WITH_PIPE
 
@@ -40,6 +42,7 @@
    sock->stream.dtype             = XIODATA_PIPE;
    sock->stream.fd                = filedes[0];
    sock->stream.para.bipipe.fdout = filedes[1];
+   sock->stream.para.bipipe.socktype = SOCK_STREAM; 	/* due to socketpair reuse */
    applyopts_cloexec(sock->stream.fd,                opts);
    applyopts_cloexec(sock->stream.para.bipipe.fdout, opts);
 
diff --git a/xio-pipe.h b/xio-pipe.h
index 34d95fa..1ea8ba9 100644
--- a/xio-pipe.h
+++ b/xio-pipe.h
@@ -7,6 +7,4 @@
 
 extern const struct addrdesc xioaddr_pipe;
 
-extern int xioopen_fifo_unnamed(char *arg, xiofile_t *sock);
-
 #endif /* !defined(__xio_pipe_h_included) */
diff --git a/xio-socket.c b/xio-socket.c
index 81b827a..9af7104 100644
--- a/xio-socket.c
+++ b/xio-socket.c
@@ -202,7 +202,6 @@
 const struct optdesc opt_bind        = { "bind",      NULL, OPT_BIND,        GROUP_SOCKET, PH_BIND, TYPE_STRING,OFUNC_SPEC };
 const struct optdesc opt_connect_timeout = { "connect-timeout", NULL, OPT_CONNECT_TIMEOUT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_TIMEVAL, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.connect_timeout) };
 const struct optdesc opt_protocol_family = { "protocol-family", "pf", OPT_PROTOCOL_FAMILY, GROUP_SOCKET, PH_PRESOCKET,  TYPE_STRING,  OFUNC_SPEC };
-const struct optdesc opt_protocol        = { "protocol",        NULL, OPT_PROTOCOL,        GROUP_SOCKET, PH_PRESOCKET,  TYPE_STRING,  OFUNC_SPEC };
 
 /* generic setsockopt() options */
 const struct optdesc opt_setsockopt        = { "setsockopt",        "sockopt",        OPT_SETSOCKOPT_BIN,        GROUP_SOCKET,PH_CONNECTED, TYPE_INT_INT_BIN,     OFUNC_SOCKOPT_GENERIC, 0, 0 };
diff --git a/xio-socketpair.c b/xio-socketpair.c
new file mode 100644
index 0000000..49396af
--- /dev/null
+++ b/xio-socketpair.c
@@ -0,0 +1,102 @@
+/* source: xio-socketpair.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 socketpair type */
+
+#include "xiosysincludes.h"
+#include "xioopen.h"
+
+#include "xio-named.h"
+
+#include "xio-socketpair.h"
+
+
+#if WITH_SOCKETPAIR
+
+static int xioopen_socketpair(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3);
+
+
+const struct addrdesc xioaddr_socketpair   = { "SOCKETPAIR",   3, xioopen_socketpair,  GROUP_FD|GROUP_SOCKET, 0, 0, 0 HELP(":<filename>") };
+
+
+/* open a socketpair */
+static int xioopen_socketpair(
+	int argc,
+	const char *argv[],
+	struct opt *opts,
+	int xioflags,
+	xiofile_t *xfd,
+	groups_t groups ,
+	int dummy1,
+	int dummy2,
+	int dummy3)
+{
+   struct single *sfd;
+   struct opt *opts2;
+   int pf = PF_UNIX;
+   int protocol = 0;
+   int filedes[2];
+   int numleft;
+   int result;
+
+   if (argc != 1) {
+      Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
+   }
+
+   sfd = &xfd->stream;
+   sfd->para.bipipe.socktype = SOCK_DGRAM;
+   if (applyopts_single(sfd, opts, PH_INIT) < 0)  return -1;
+   applyopts(-1, opts, PH_INIT);
+   retropt_int(opts, OPT_PROTOCOL_FAMILY, &pf);
+   retropt_int(opts, OPT_SO_TYPE, &sfd->para.bipipe.socktype);
+   retropt_int(opts, OPT_SO_PROTOTYPE, &protocol);
+
+   if (Socketpair(pf, sfd->para.bipipe.socktype, protocol, filedes) != 0) {
+      Error5("socketpair(%d, %d, %d, %p): %s", pf, sfd->para.bipipe.socktype, protocol, filedes, strerror(errno));
+      return -1;
+   }
+   Info2("socketpair({%d,%d})", filedes[0], filedes[1]);
+
+   sfd->tag               = XIO_TAG_RDWR;
+   if (sfd->para.bipipe.socktype == SOCK_STREAM) {
+      sfd->dtype             = XIOREAD_STREAM|XIOWRITE_PIPE;
+   } else {
+      sfd->dtype             = XIOREAD_RECV|XIOREAD_RECV_NOCHECK|XIOWRITE_PIPE;
+   }
+   sfd->fd                = filedes[0];
+   sfd->para.bipipe.fdout = filedes[1];
+   applyopts_cloexec(sfd->fd,                opts);
+   applyopts_cloexec(sfd->para.bipipe.fdout, opts);
+
+   /* one-time and input-direction options, no second application */
+   retropt_bool(opts, OPT_IGNOREEOF, &sfd->ignoreeof);
+
+   /* here we copy opts! */
+   if ((opts2 = copyopts(opts, GROUP_SOCKET)) == NULL) {
+      return STAT_NORETRY;
+   }
+
+   /* apply options to first FD */
+   if ((result = applyopts(sfd->fd, opts, PH_ALL)) < 0) {
+      return result;
+   }
+   if ((result = applyopts_single(sfd, opts, PH_ALL)) < 0) {
+      return result;
+   }
+
+   /* apply options to second FD */
+   if ((result = applyopts(sfd->para.bipipe.fdout, opts2, PH_ALL)) < 0)
+   {
+      return result;
+   }
+
+   if ((numleft = leftopts(opts)) > 0) {
+      Error1("%d option(s) could not be used", numleft);
+      showleft(opts);
+   }
+   Notice("writing to and reading from unnamed socketpair");
+   return 0;
+}
+
+#endif /* WITH_SOCKETPAIR */
diff --git a/xio-socketpair.h b/xio-socketpair.h
new file mode 100644
index 0000000..2f92f70
--- /dev/null
+++ b/xio-socketpair.h
@@ -0,0 +1,10 @@
+/* source: xio-socketpair.h */
+/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
+/* Published under the GNU General Public License V.2, see file COPYING */
+
+#ifndef __xio_socketpair_h_included
+#define __xio_socketpair_h_included 1
+
+const extern struct addrdesc xioaddr_socketpair;
+
+#endif /* !defined(__xio_socketpair_h_included) */
diff --git a/xio.h b/xio.h
index 1d72fa3..6c3d057 100644
--- a/xio.h
+++ b/xio.h
@@ -61,6 +61,7 @@
 #define XIOREAD_RECV_ONESHOT	0x0008	/* give EOF after first packet */
 #define XIOREAD_RECV_SKIPIP	0x0010	/* recv, skip IPv4 header */
 #define XIOREAD_RECV_FROM	0x0020	/* remember peer for replying */
+#define XIOREAD_RECV_NOCHECK	0x0040	/* do not check peer */
 
 /* combinations */
 #define XIODATA_MASK		(XIODATA_READMASK|XIODATA_WRITEMASK)
@@ -211,6 +212,7 @@
    union {
       struct {
 	 int fdout;		/* use fd for output */
+	 int socktype;
       } bipipe;
 #if _WITH_SOCKET
       struct {
@@ -242,8 +244,8 @@
       } socket;
 #endif /* _WITH_SOCKET */
       struct {
-	 pid_t pid;		/* child PID, with EXEC: */
 	 int fdout;		/* use fd for output if two pipes */
+	 pid_t pid;		/* child PID, with EXEC: */
 	 struct timeval sitout_eio;
       } exec;
 #if WITH_READLINE
diff --git a/xiomodes.h b/xiomodes.h
index 7a20547..8ab1b9a 100644
--- a/xiomodes.h
+++ b/xiomodes.h
@@ -15,6 +15,7 @@
 #include "xio-creat.h"
 #include "xio-gopen.h"
 #include "xio-pipe.h"
+#include "xio-socketpair.h"
 #if _WITH_SOCKET
 #include "xio-socket.h"
 #include "xio-listen.h"
diff --git a/xioopen.c b/xioopen.c
index 1a87ac8..3aeed05 100644
--- a/xioopen.c
+++ b/xioopen.c
@@ -193,6 +193,9 @@
    { "SOCKET-RECVFROM",		&xioaddr_socket_recvfrom },
    { "SOCKET-SENDTO",		&xioaddr_socket_sendto },
 #endif
+#if WITH_SOCKETPAIR
+   { "SOCKETPAIR",		&xioaddr_socketpair },
+#endif
 #if WITH_SOCKS4
    { "SOCKS",			&xioaddr_socks4_connect },
    { "SOCKS4",			&xioaddr_socks4_connect },
diff --git a/xioopts.h b/xioopts.h
index c3f1359..509809e 100644
--- a/xioopts.h
+++ b/xioopts.h
@@ -152,7 +152,6 @@
 #define GROUP_FILE GROUP_REG
 #define GROUP_SOCKET	0x00000020
 #define GROUP_READLINE	0x00000040
-
 #define GROUP_NAMED	0x00000100	/* file system entry */
 #define GROUP_OPEN	0x00000200	/* flags for open() */
 #define GROUP_EXEC	0x00000400	/* program or script execution */
diff --git a/xioread.c b/xioread.c
index 36bbe0b..1399012 100644
--- a/xioread.c
+++ b/xioread.c
@@ -134,7 +134,27 @@
 
 #if _WITH_SOCKET
    case XIOREAD_RECV:
-     if (pipe->dtype & XIOREAD_RECV_FROM) {
+     if (pipe->dtype & XIOREAD_RECV_NOCHECK) {
+	/* No need to check peer address */
+      do {
+	 bytes =
+	    Recv(pipe->fd, buff, bufsiz, 0);
+      } while (bytes < 0 && errno == EINTR);
+      if (bytes < 0) {
+	 _errno = errno;
+	 Error3("recvfrom(%d, %p, "F_Zu", 0", pipe->fd, buff, bufsiz);
+	 errno = _errno;
+	 return -1;
+      }
+      Notice1("received packet with "F_Zu" bytes", bytes);
+      if (bytes == 0) {
+	 if (!pipe->para.socket.null_eof) {
+	    errno = EAGAIN; return -1;
+	 }
+	 return bytes;
+      }
+
+     } else if (pipe->dtype & XIOREAD_RECV_FROM) {
       /* Receiving packets in addresses of RECVFROM types, the sender address
 	   has already been determined in OPEN phase. */
       Debug1("%s(): XIOREAD_RECV and XIOREAD_RECV_FROM (peer checks already done)",
@@ -375,7 +395,7 @@
       return -1;
 #endif /* !(WITH_RAWIP || WITH_UDP || WITH_UNIX) */
 
-     } else /* ~XIOREAD_RECV_FROM */ {
+     } else /* ~(XIOREAD_RECV_FROM|XIOREAD_RECV_FROM) */ {
 	/* Receiving packets without planning to answer to the sender, but we
 	   might need sender info for some checks, thus we use recvfrom() */
       struct msghdr msgh = {0};
diff --git a/xiowrite.c b/xiowrite.c
index 143e1ac..769a3fd 100644
--- a/xiowrite.c
+++ b/xiowrite.c
@@ -114,7 +114,11 @@
 #endif /* _WITH_SOCKET */
 
    case XIOWRITE_PIPE:
-      writt = Write(pipe->para.bipipe.fdout, buff, bytes);
+      if (pipe->para.bipipe.socktype == SOCK_STREAM) {
+	 writt = Write(pipe->para.bipipe.fdout, buff, bytes);
+      } else {
+	 writt = Send(pipe->para.bipipe.fdout, buff, bytes, 0);
+      }
       _errno = errno;
       if (writt < 0) {
 	 Error4("write(%d, %p, "F_Zu"): %s",