From 59657427aff19fb0f96c2be7425f9b7912bb6d69 Mon Sep 17 00:00:00 2001
From: Vincent Torri <vincent.torri@gmail.com>
Date: Mon, 3 Apr 2017 06:16:56 +0200
Subject: [PATCH 2/2] Evil: fix fcntl() with sockets

On Windows, fd and sockets are different. Sockets are actually HANDLES, hence
_get_osfhandle() should not be used with sockets, and GetHandleInformation()
 and SetHandleInformation() can be used directly with sockets.

This is fixed by adding a function to test if the 'fd passed to fcntl() is a
socket or not.
---
 src/lib/evil/evil_fcntl.c | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

diff --git a/src/lib/evil/evil_fcntl.c b/src/lib/evil/evil_fcntl.c
index 188e476fa9..df79c3605f 100644
--- a/src/lib/evil/evil_fcntl.c
+++ b/src/lib/evil/evil_fcntl.c
@@ -11,6 +11,21 @@
 #include "evil_macro.h"
 #include "evil_fcntl.h"
 
+/* SOCKET is defined as a uintptr_t, so passing a fd (int) is not a problem */
+static int
+_is_socket(SOCKET s)
+{
+   fd_set rfds;
+   struct timeval tv;
+
+   tv.tv_sec = 0.00000001;
+   tv.tv_usec = 0;
+   FD_ZERO(&rfds);
+   FD_SET(s, &rfds);
+
+   return select(1, &rfds, NULL, NULL, &tv) != SOCKET_ERROR;
+}
+
 
 /*
  * port of fcntl function
@@ -29,17 +44,19 @@ int fcntl(int fd, int cmd, ...)
         HANDLE  h;
         DWORD flag;
 
-        h = (HANDLE)_get_osfhandle(fd);
+        h = _is_socket(fd) ? (HANDLE)fd : (HANDLE)_get_osfhandle(fd);
         if (h == INVALID_HANDLE_VALUE)
           return -1;
 
-	if (!GetHandleInformation(h, &flag))
+	if (GetHandleInformation(h, &flag))
           {
-             /* FIXME: should we close h ? MSDN seems to say that */
-             return -1;
+             if (flag == HANDLE_FLAG_INHERIT)
+               return FD_CLOEXEC;
+
+             return 0;
           }
 
-	res = 0;
+	return -1;
      }
 
    if (cmd == F_SETFD)
@@ -47,7 +64,7 @@ int fcntl(int fd, int cmd, ...)
         HANDLE  h;
         long flag;
 
-        h = (HANDLE)_get_osfhandle(fd);
+        h = _is_socket(fd) ? (HANDLE)fd : (HANDLE)_get_osfhandle(fd);
         if (h == INVALID_HANDLE_VALUE)
           return -1;
 
@@ -55,7 +72,7 @@ int fcntl(int fd, int cmd, ...)
         if (flag == FD_CLOEXEC)
           {
              if (SetHandleInformation(h, HANDLE_FLAG_INHERIT, 0))
-               res = 0;
+               return 0;
           }
      }
    else if (cmd == F_GETFL)
-- 
2.11.0

