This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[asperl] tweak makefiles
[perl5.git] / win32 / win32sck.c
index 559691a..bcf180a 100644 (file)
 #define WIN32IO_IS_STDIO
 #define WIN32SCK_IS_STDSCK
 #define WIN32_LEAN_AND_MEAN
+#ifdef __GNUC__
+#define Win32_Winsock
+#  ifdef __cplusplus
+#undef __attribute__           /* seems broken in 2.8.0 */
+#define __attribute__(p)
+#  endif
+#endif
 #include <windows.h>
 #include "EXTERN.h"
 #include "perl.h"
+
+#if defined(PERL_OBJECT)
+#define NO_XSLOCKS
+extern CPerlObj* pPerl;
+#include "XSUB.h"
+#endif
+
 #include <sys/socket.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #      define TO_SOCKET(x)     (x)
 #endif /* USE_SOCKETS_AS_HANDLES */
 
+#ifdef USE_THREADS
 #define StartSockets() \
     STMT_START {                                       \
        if (!wsock_started)                             \
            start_sockets();                            \
+       set_socktype();                         \
     } STMT_END
+#else
+#define StartSockets() \
+    STMT_START {                                       \
+       if (!wsock_started) {                           \
+           start_sockets();                            \
+           set_socktype();                             \
+       }                                               \
+    } STMT_END
+#endif
 
 #define EndSockets() \
     STMT_START {                                       \
@@ -54,7 +79,18 @@ static struct servent* win32_savecopyservent(struct servent*d,
                                              struct servent*s,
                                              const char *proto);
 
+#ifdef USE_THREADS
+#ifdef USE_DECLSPEC_THREAD
 __declspec(thread) struct servent myservent;
+__declspec(thread) int init_socktype;
+#else
+#define myservent (thr->i.Wservent)
+#define init_socktype (thr->i.Winit_socktype)
+#endif
+#else
+static struct servent myservent;
+#endif
+
 static int wsock_started = 0;
 
 void
@@ -63,7 +99,6 @@ start_sockets(void)
     unsigned short version;
     WSADATA retdata;
     int ret;
-    int iSockOpt = SO_SYNCHRONOUS_NONALERT;
 
     /*
      * initalize the winsock interface and insure that it is
@@ -76,15 +111,28 @@ start_sockets(void)
        croak("Could not find version 1.1 of winsock dll\n");
 
     /* atexit((void (*)(void)) EndSockets); */
+    wsock_started = 1;
+}
 
+void
+set_socktype(void)
+{
 #ifdef USE_SOCKETS_AS_HANDLES
+#ifdef USE_THREADS
+    dTHR;
+    if(!init_socktype) {
+#endif
+    int iSockOpt = SO_SYNCHRONOUS_NONALERT;
     /*
      * Enable the use of sockets as filehandles
      */
     setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
                (char *)&iSockOpt, sizeof(iSockOpt));
+#ifdef USE_THREADS
+    init_socktype = 1;
+    }
+#endif
 #endif /* USE_SOCKETS_AS_HANDLES */
-    wsock_started = 1;
 }
 
 
@@ -257,6 +305,15 @@ win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const
     int i, fd, bit, offset;
     FD_SET nrd, nwr, nex, *prd, *pwr, *pex;
 
+    /* winsock seems incapable of dealing with all three null fd_sets,
+     * so do the (millisecond) sleep as a special case
+     */
+    if (!(rd || wr || ex)) {
+       Sleep(timeout->tv_sec  * 1000 +
+             timeout->tv_usec / 1000);         /* do the best we can */
+       return 0;
+    }
+    StartSockets();
     PERL_FD_ZERO(&dummy);
     if (!rd)
        rd = &dummy, prd = NULL;
@@ -432,7 +489,8 @@ struct servent *
 win32_getservbyname(const char *name, const char *proto)
 {
     struct servent *r;
-   
+    dTHR;    
+
     SOCKET_TEST(r = getservbyname(name, proto), NULL);
     if (r) {
        r = win32_savecopyservent(&myservent, r, proto);
@@ -444,6 +502,7 @@ struct servent *
 win32_getservbyport(int port, const char *proto)
 {
     struct servent *r;
+    dTHR; 
 
     SOCKET_TEST(r = getservbyport(port, proto), NULL);
     if (r) {
@@ -452,6 +511,28 @@ win32_getservbyport(int port, const char *proto)
     return r;
 }
 
+int
+win32_ioctl(int i, unsigned int u, char *data)
+{
+    u_long argp = (u_long)data;
+    int retval;
+
+    if (!wsock_started) {
+       croak("ioctl implemented only on sockets");
+       /* NOTREACHED */
+    }
+
+    retval = ioctlsocket(TO_SOCKET(i), (long)u, &argp);
+    if (retval == SOCKET_ERROR) {
+       if (WSAGetLastError() == WSAENOTSOCK) {
+           croak("ioctl implemented only on sockets");
+           /* NOTREACHED */
+       }
+       errno = WSAGetLastError();
+    }
+    return retval;
+}
+
 char FAR *
 win32_inet_ntoa(struct in_addr in)
 {
@@ -568,7 +649,7 @@ win32_savecopyservent(struct servent*d, struct servent*s, const char *proto)
        d->s_proto = s->s_proto;
     else
 #endif
-       if (proto && strlen(proto))
+    if (proto && strlen(proto))
        d->s_proto = (char *)proto;
     else
        d->s_proto = "tcp";