XSLoader revisted
[p5sagit/p5-mst-13.2.git] / ext / Socket / Socket.xs
index 4191097..139e9cb 100644 (file)
@@ -3,11 +3,15 @@
 #include "perl.h"
 #include "XSUB.h"
 
+#include <stddef.h>
+
 #ifndef VMS
 # ifdef I_SYS_TYPES
 #  include <sys/types.h>
 # endif
-# include <sys/socket.h>
+# if !defined(ultrix) /* Avoid double definition. */
+#   include <sys/socket.h>
+# endif
 # if defined(USE_SOCKS) && defined(I_SOCKS)
 #   include <socks.h>
 # endif
 # if defined(NeXT) || defined(__NeXT__)
 #  include <netinet/in_systm.h>
 # endif
+# if defined(__sgi) && !defined(AF_LINK) && defined(PF_LINK) && PF_LINK == AF_LNK
+#  undef PF_LINK
+# endif
 # ifdef I_NETINET_IN
 #  include <netinet/in.h>
 # endif
 # ifdef I_NETDB
-#  include <netdb.h>
+#  if !defined(ultrix)  /* Avoid double definition. */
+#   include <netdb.h>
+#  endif
 # endif
 # ifdef I_ARPA_INET
 #  include <arpa/inet.h>
@@ -209,11 +218,11 @@ not_here(char *s)
 *
 * --jhi */
 
-#include "constants.c"
+#include "const-c.inc"
 
 MODULE = Socket                PACKAGE = Socket
 
-INCLUDE: constants.xs
+INCLUDE: const-xs.inc
 
 void
 inet_aton(host)
@@ -222,7 +231,10 @@ inet_aton(host)
        {
        struct in_addr ip_address;
        struct hostent * phe;
-       int ok = inet_aton(host, &ip_address);
+       int ok =
+               (host != NULL) &&
+               (*host != '\0') &&
+               inet_aton(host, &ip_address);
 
        if (!ok && (phe = gethostbyname(host))) {
                Copy( phe->h_addr, &ip_address, phe->h_length, char );
@@ -245,7 +257,7 @@ inet_ntoa(ip_address_sv)
        char * ip_address;
        if (DO_UTF8(ip_address_sv) && !sv_utf8_downgrade(ip_address_sv, 1))
             croak("Wide character in Socket::inet_ntoa");
-       ip_address = SvPV(ip_address_sv, addrlen);
+       ip_address = SvPVbyte(ip_address_sv, addrlen);
        if (addrlen == sizeof(addr) || addrlen == 4)
                addr.s_addr =
                    (ip_address[0] & 0xFF) << 24 |
@@ -258,8 +270,9 @@ inet_ntoa(ip_address_sv)
                      addrlen, sizeof(addr));
        /* We could use inet_ntoa() but that is broken
         * in HP-UX + GCC + 64bitint (returns "0.0.0.0"),
-        * so let's use this sprintf() workaround everywhere. */
-       New(1138, addr_str, 4 * 3 + 3 + 1, char);
+        * so let's use this sprintf() workaround everywhere.
+        * This is also more threadsafe than using inet_ntoa(). */
+       New(1138, addr_str, 4 * 3 + 3 + 1, char); /* IPv6? */
        sprintf(addr_str, "%d.%d.%d.%d",
                ((addr.s_addr >> 24) & 0xFF),
                ((addr.s_addr >> 16) & 0xFF),
@@ -270,6 +283,20 @@ inet_ntoa(ip_address_sv)
        }
 
 void
+sockaddr_family(sockaddr)
+       SV *    sockaddr
+       PREINIT:
+       STRLEN sockaddr_len;
+       char *sockaddr_pv = SvPVbyte(sockaddr, sockaddr_len);
+       CODE:
+       if (sockaddr_len < offsetof(struct sockaddr, sa_data)) {
+           croak("Bad arg length for %s, length is %d, should be at least %d",
+                 "Socket::sockaddr_family", sockaddr_len,
+                 offsetof(struct sockaddr, sa_data));
+       }
+       ST(0) = sv_2mortal(newSViv(((struct sockaddr*)sockaddr_pv)->sa_family));
+
+void
 pack_sockaddr_un(pathname)
        char *  pathname
        CODE:
@@ -324,7 +351,7 @@ unpack_sockaddr_un(sun_sv)
 #ifdef I_SYS_UN
        struct sockaddr_un addr;
        STRLEN sockaddrlen;
-       char * sun_ad = SvPV(sun_sv,sockaddrlen);
+       char * sun_ad = SvPVbyte(sun_sv,sockaddrlen);
        char * e;
 #   ifndef __linux__
        /* On Linux sockaddrlen on sockets returned by accept, recvfrom,
@@ -344,10 +371,10 @@ unpack_sockaddr_un(sun_sv)
                        addr.sun_family,
                        AF_UNIX);
        }
-       e = addr.sun_path;
-       while (*e && e < addr.sun_path + sizeof addr.sun_path)
+       e = (char*)addr.sun_path;
+       while (*e && e < (char*)addr.sun_path + sizeof addr.sun_path)
            ++e;
-       ST(0) = sv_2mortal(newSVpvn(addr.sun_path, e - addr.sun_path));
+       ST(0) = sv_2mortal(newSVpvn(addr.sun_path, e - (char*)addr.sun_path));
 #else
        ST(0) = (SV *) not_here("unpack_sockaddr_un");
 #endif
@@ -365,7 +392,7 @@ pack_sockaddr_in(port, ip_address_sv)
        char * ip_address;
        if (DO_UTF8(ip_address_sv) && !sv_utf8_downgrade(ip_address_sv, 1))
             croak("Wide character in Socket::pack_sockaddr_in");
-       ip_address = SvPV(ip_address_sv, addrlen);
+       ip_address = SvPVbyte(ip_address_sv, addrlen);
        if (addrlen == sizeof(addr) || addrlen == 4)
                addr.s_addr =
                    (ip_address[0] & 0xFF) << 24 |
@@ -392,7 +419,7 @@ unpack_sockaddr_in(sin_sv)
        struct sockaddr_in addr;
        unsigned short  port;
        struct in_addr  ip_address;
-       char *  sin = SvPV(sin_sv,sockaddrlen);
+       char *  sin = SvPVbyte(sin_sv,sockaddrlen);
        if (sockaddrlen != sizeof(addr)) {
            croak("Bad arg length for %s, length is %d, should be %d",
                        "Socket::unpack_sockaddr_in",