-m(dup2): Texinfo typo
[gnulib.git] / lib / pipe2.c
index 68677de..7def1b1 100644 (file)
 #include <errno.h>
 #include <fcntl.h>
 
+#include "binary-io.h"
+
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
 /* Native Woe32 API.  */
 
 # include <io.h>
 
+#else
+/* Unix API.  */
+
+# ifndef O_CLOEXEC
+#  define O_CLOEXEC 0
+# endif
+
+#endif
+
 int
 pipe2 (int fd[2], int flags)
 {
+#if HAVE_PIPE2
+# undef pipe2
+  /* Try the system call first, if it exists.  (We may be running with a glibc
+     that has the function but with an older kernel that lacks it.)  */
+  {
+    /* Cache the information whether the system call really exists.  */
+    static int have_pipe2_really; /* 0 = unknown, 1 = yes, -1 = no */
+    if (have_pipe2_really >= 0)
+      {
+       int result = pipe2 (fd, flags);
+       if (!(result < 0 && errno == ENOSYS))
+         {
+           have_pipe2_really = 1;
+           return result;
+         }
+       have_pipe2_really = -1;
+      }
+  }
+#endif
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Native Woe32 API.  */
+
   /* Check the supported flags.  */
   if ((flags & ~(O_CLOEXEC | O_BINARY | O_TEXT)) != 0)
     {
@@ -39,20 +73,12 @@ pipe2 (int fd[2], int flags)
     }
 
   return _pipe (fd, 4096, flags);
-}
 
 #else
 /* Unix API.  */
 
-# ifndef O_CLOEXEC
-#  define O_CLOEXEC 0
-# endif
-
-int
-pipe2 (int fd[2], int flags)
-{
   /* Check the supported flags.  */
-  if ((flags & ~(O_CLOEXEC | O_NONBLOCK)) != 0)
+  if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_TEXT | O_BINARY)) != 0)
     {
       errno = EINVAL;
       return -1;
@@ -70,9 +96,9 @@ pipe2 (int fd[2], int flags)
       int fcntl_flags;
 
       if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0
-         || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) < 0
+         || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1
          || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0
-         || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) < 0)
+         || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1)
        goto fail;
     }
 
@@ -81,12 +107,25 @@ pipe2 (int fd[2], int flags)
       int fcntl_flags;
 
       if ((fcntl_flags = fcntl (fd[1], F_GETFD, 0)) < 0
-         || fcntl (fd[1], F_SETFD, fcntl_flags | FD_CLOEXEC) < 0
+         || fcntl (fd[1], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1
          || (fcntl_flags = fcntl (fd[0], F_GETFD, 0)) < 0
-         || fcntl (fd[0], F_SETFD, fcntl_flags | FD_CLOEXEC) < 0)
+         || fcntl (fd[0], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1)
        goto fail;
     }
 
+# if O_BINARY
+  if (flags & O_BINARY)
+    {
+      setmode (fd[1], O_BINARY);
+      setmode (fd[0], O_BINARY);
+    }
+  else if (flags & O_TEXT)
+    {
+      setmode (fd[1], O_TEXT);
+      setmode (fd[0], O_TEXT);
+    }
+# endif
+
   return 0;
 
  fail:
@@ -97,6 +136,6 @@ pipe2 (int fd[2], int flags)
     errno = saved_errno;
     return -1;
   }
-}
 
 #endif
+}