Change sense from "incomplete" to "implemented but needs more work" in perlunicode.pod
[p5sagit/p5-mst-13.2.git] / ext / Socket / Socket.xs
index b8e3408..e089829 100644 (file)
@@ -1,3 +1,4 @@
+#define PERL_NO_GET_CONTEXT
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
@@ -6,28 +7,36 @@
 # ifdef I_SYS_TYPES
 #  include <sys/types.h>
 # endif
-#include <sys/socket.h>
-#ifdef MPE
-# define PF_INET AF_INET
-# define PF_UNIX AF_UNIX
-# define SOCK_RAW 3
-#endif
-#ifdef I_SYS_UN
-#include <sys/un.h>
-#endif
+# include <sys/socket.h>
+# if defined(USE_SOCKS) && defined(I_SOCKS)
+#   include <socks.h>
+# endif 
+# ifdef MPE
+#  define PF_INET AF_INET
+#  define PF_UNIX AF_UNIX
+#  define SOCK_RAW 3
+# endif
+# ifdef I_SYS_UN
+#  include <sys/un.h>
+# endif
+/* XXX Configure test for <netinet/in_systm.h needed XXX */
+# if defined(NeXT) || defined(__NeXT__)
+#  include <netinet/in_systm.h>
+# endif
 # ifdef I_NETINET_IN
 #  include <netinet/in.h>
 # endif
-#include <netdb.h>
-#ifdef I_ARPA_INET
-# include <arpa/inet.h>
-#endif
+# ifdef I_NETDB
+#  include <netdb.h>
+# endif
+# ifdef I_ARPA_INET
+#  include <arpa/inet.h>
+# endif
+# ifdef I_NETINET_TCP
+#  include <netinet/tcp.h>
+# endif
 #else
-#include "sockadapt.h"
-#endif
-
-#ifndef WIN32 /* I_NETINET_TCP */
-#include <netinet/tcp.h>
+# include "sockadapt.h"
 #endif
 
 #ifdef I_SYSUIO
 #endif
 
 #ifndef AF_NBS
-#undef PF_NBS
+# undef PF_NBS
 #endif
 
 #ifndef AF_X25
-#undef PF_X25
+# undef PF_X25
 #endif
 
 #ifndef INADDR_NONE
-#define INADDR_NONE    0xffffffff
+# define INADDR_NONE   0xffffffff
 #endif /* INADDR_NONE */
 #ifndef INADDR_BROADCAST
-#define INADDR_BROADCAST       0xffffffff
+# define INADDR_BROADCAST      0xffffffff
 #endif /* INADDR_BROADCAST */
 #ifndef INADDR_LOOPBACK
-#define INADDR_LOOPBACK         0x7F000001
+# define INADDR_LOOPBACK         0x7F000001
 #endif /* INADDR_LOOPBACK */
 
 #ifndef HAS_INET_ATON
@@ -64,6 +73,7 @@
 static int
 my_inet_aton(register const char *cp, struct in_addr *addr)
 {
+       dTHX;
        register U32 val;
        register int base;
        register char c;
@@ -656,6 +666,24 @@ constant(char *name, int arg)
 #else
            goto not_there;
 #endif
+       if (strEQ(name, "SHUT_RD"))
+#ifdef SHUT_RD
+           return SHUT_RD;
+#else
+           return 0;
+#endif
+       if (strEQ(name, "SHUT_RDWR"))
+#ifdef SHUT_RDWR
+           return SHUT_RDWR;
+#else
+           return 2;
+#endif
+       if (strEQ(name, "SHUT_WR"))
+#ifdef SHUT_WR
+           return SHUT_WR;
+#else
+           return 1;
+#endif
        if (strEQ(name, "SOCK_DGRAM"))
 #ifdef SOCK_DGRAM
            return SOCK_DGRAM;
@@ -930,12 +958,37 @@ pack_sockaddr_un(pathname)
 #ifdef I_SYS_UN
        struct sockaddr_un sun_ad; /* fear using sun */
        STRLEN len;
+
        Zero( &sun_ad, sizeof sun_ad, char );
        sun_ad.sun_family = AF_UNIX;
        len = strlen(pathname);
        if (len > sizeof(sun_ad.sun_path))
            len = sizeof(sun_ad.sun_path);
+#  ifdef OS2   /* Name should start with \socket\ and contain backslashes! */
+       {
+           int off;
+           char *s, *e;
+
+           if (pathname[0] != '/' && pathname[0] != '\\')
+               croak("Relative UNIX domain socket name '%s' unsupported", pathname);
+           else if (len < 8 
+                    || pathname[7] != '/' && pathname[7] != '\\'
+                    || !strnicmp(pathname + 1, "socket", 6))
+               off = 7;
+           else
+               off = 0;                /* Preserve names starting with \socket\ */
+           Copy( "\\socket", sun_ad.sun_path, off, char);
+           Copy( pathname, sun_ad.sun_path + off, len, char );
+
+           s = sun_ad.sun_path + off - 1;
+           e = s + len + 1;
+           while (++s < e)
+               if (*s = '/')
+                   *s = '\\';
+       }
+#  else        /* !( defined OS2 ) */ 
        Copy( pathname, sun_ad.sun_path, len, char );
+#  endif
        ST(0) = sv_2mortal(newSVpvn((char *)&sun_ad, sizeof sun_ad));
 #else
        ST(0) = (SV *) not_here("pack_sockaddr_un");
@@ -953,12 +1006,15 @@ unpack_sockaddr_un(sun_sv)
        STRLEN sockaddrlen;
        char * sun_ad = SvPV(sun_sv,sockaddrlen);
        char * e;
-
+#   ifndef __linux__
+       /* On Linux sockaddrlen on sockets returned by accept, recvfrom,
+          getpeername and getsockname is not equal to sizeof(addr). */
        if (sockaddrlen != sizeof(addr)) {
            croak("Bad arg length for %s, length is %d, should be %d",
                        "Socket::unpack_sockaddr_un",
                        sockaddrlen, sizeof(addr));
        }
+#   endif
 
        Copy( sun_ad, &addr, sizeof addr, char );