diff --git a/win32/perllib.c b/win32/perllib.c index 64d9fdb8487f..86fc7b795cc4 100644 --- a/win32/perllib.c +++ b/win32/perllib.c @@ -253,8 +253,10 @@ DllMain(HINSTANCE hModule, /* DLL module handle */ A. Not called at all. B. Called after memory allocation for Heap has been forcibly removed by OS. PerlIO_cleanup() was done here but fails (B). - */ + */ +#ifndef WIN32_NO_SOCKETS EndSockets(); +#endif #if defined(USE_ITHREADS) if (PL_curinterp) FREE_THREAD_KEY; diff --git a/win32/win32.c b/win32/win32.c index 0f54fc61344f..650e600a6775 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -5461,13 +5461,12 @@ Perl_win32_init(int *argcp, char ***argvp) */ InitCommonControls(); - WSADATA wsadata; - WSAStartup(MAKEWORD(2, 2), &wsadata); - g_osver.dwOSVersionInfoSize = sizeof(g_osver); GetVersionEx(&g_osver); +#ifndef WIN32_NO_SOCKETS win32_hook_closehandle_in_crt(); +#endif ansify_path(); @@ -5516,7 +5515,9 @@ Perl_win32_term(void) RegCloseKey(HKCU_Perl_hnd); /* the handles are in an undefined state until the next PERL_SYS_INIT3 */ #endif +#ifndef WIN32_NO_SOCKETS win32_unhook_closehandle_in_crt(); +#endif } void diff --git a/win32/win32.h b/win32/win32.h index 193990e9bb27..9d28152ace66 100644 --- a/win32/win32.h +++ b/win32/win32.h @@ -15,6 +15,12 @@ /* Win32 only optimizations for faster building */ #ifdef PERL_IS_MINIPERL +/* this macro will remove Winsock only on miniperl, PERL_IMPLICIT_SYS and + * makedef.pl create dependencies that will keep Winsock linked in even with + * this macro defined, even though sockets will be umimplemented from a script + * level in full perl + */ +# define WIN32_NO_SOCKETS /* less I/O calls during each require */ # define PERL_DISABLE_PMC @@ -25,6 +31,29 @@ # define PERL_TEXTMODE_SCRIPTS #endif +#ifdef WIN32_NO_SOCKETS +# undef HAS_SOCKET +# undef HAS_GETPROTOBYNAME +# undef HAS_GETPROTOBYNUMBER +# undef HAS_GETPROTOENT +# undef HAS_GETNETBYNAME +# undef HAS_GETNETBYADDR +# undef HAS_GETNETENT +# undef HAS_GETSERVBYNAME +# undef HAS_GETSERVBYPORT +# undef HAS_GETSERVENT +# undef HAS_GETHOSTBYNAME +# undef HAS_GETHOSTBYADDR +# undef HAS_GETHOSTENT +# undef HAS_SELECT +# undef HAS_IOCTL +# undef HAS_NTOHL +# undef HAS_HTONL +# undef HAS_HTONS +# undef HAS_NTOHS +# define WIN32SCK_IS_STDSCK +#endif + #if defined(PERL_IMPLICIT_SYS) # define DYNAMIC_ENV_FETCH # define HAS_GETENV_LEN diff --git a/win32/win32sck.c b/win32/win32sck.c index 7289a47d9b0b..4c99686c5184 100644 --- a/win32/win32sck.c +++ b/win32/win32sck.c @@ -33,8 +33,17 @@ #define OPEN_SOCKET(x) win32_open_osfhandle(x,O_RDWR|O_BINARY) #define TO_SOCKET(x) _get_osfhandle(x) +#ifndef WIN32_NO_SOCKETS + +#define StartSockets() \ + STMT_START { \ + if (!wsock_started) \ + start_sockets(); \ + } STMT_END + #define SOCKET_TEST(x, y) \ STMT_START { \ + StartSockets(); \ if((x) == (y)) \ { \ int wsaerr = WSAGetLastError(); \ @@ -43,11 +52,26 @@ } \ } STMT_END +#else + +# define StartSockets() + +# define SOCKET_TEST(x, y) \ + STMT_START { \ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); \ + errno = ENOSYS; \ + } STMT_END + +#endif + #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR) static struct servent* win32_savecopyservent(struct servent*d, struct servent*s, const char *proto); +#ifndef WIN32_NO_SOCKETS +static int wsock_started = 0; +#endif #ifdef WIN32_DYN_IOINFO_SIZE EXTERN_C Size_t w32_ioinfo_size; @@ -56,7 +80,10 @@ EXTERN_C Size_t w32_ioinfo_size; EXTERN_C void EndSockets(void) { - WSACleanup(); +#ifndef WIN32_NO_SOCKETS + if (wsock_started) + WSACleanup(); +#endif } /* Translate WSAExxx values to corresponding Exxx values where possible. Not all @@ -316,27 +343,65 @@ convert_errno_to_wsa_error(int err) } #endif /* ERRNO_HAS_POSIX_SUPPLEMENT */ +void +start_sockets(void) +{ +#ifndef WIN32_NO_SOCKETS + unsigned short version; + WSADATA retdata; + int ret; + + /* + * initalize the winsock interface and insure that it is + * cleaned up at exit. + */ + version = 0x2; + if(ret = WSAStartup(version, &retdata)) + Perl_croak_nocontext("Unable to locate winsock library!\n"); + if(retdata.wVersion != version) + Perl_croak_nocontext("Could not find version 2.0 of winsock dll\n"); + + /* atexit((void (*)(void)) EndSockets); */ + wsock_started = 1; +#endif +} + +/* in no sockets Win32 builds, these use the inline functions defined in + * perl.h + */ u_long win32_htonl(u_long hostlong) { +#ifndef WIN32_NO_SOCKETS + StartSockets(); +#endif return htonl(hostlong); } u_short win32_htons(u_short hostshort) { +#ifndef WIN32_NO_SOCKETS + StartSockets(); +#endif return htons(hostshort); } u_long win32_ntohl(u_long netlong) { +#ifndef WIN32_NO_SOCKETS + StartSockets(); +#endif return ntohl(netlong); } u_short win32_ntohs(u_short netshort) { +#ifndef WIN32_NO_SOCKETS + StartSockets(); +#endif return ntohs(netshort); } @@ -345,88 +410,143 @@ win32_ntohs(u_short netshort) SOCKET win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen) { +#ifndef WIN32_NO_SOCKETS SOCKET r; SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET); return OPEN_SOCKET(r); +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return INVALID_SOCKET; +#endif } int win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } int win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } int win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } int win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } int win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return INVALID_SOCKET; +#endif } int win32_ioctlsocket(SOCKET s, long cmd, u_long *argp) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return INVALID_SOCKET; +#endif } int win32_listen(SOCKET s, int backlog) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } int win32_recv(SOCKET s, char *buf, int len, int flags) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } int win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen) { +#ifndef WIN32_NO_SOCKETS int r; int frombufsize = *fromlen; @@ -438,17 +558,25 @@ win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, i if (r != SOCKET_ERROR && frombufsize == *fromlen) (void)win32_getpeername(s, from, fromlen); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } /* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */ int win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout) { +#ifndef WIN32_NO_SOCKETS int r; int i, fd, save_errno = errno; FD_SET nrd, nwr, nex; bool just_sleep = TRUE; + StartSockets(); + FD_ZERO(&nrd); FD_ZERO(&nwr); FD_ZERO(&nex); @@ -505,52 +633,87 @@ win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const } errno = save_errno; return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } int win32_send(SOCKET s, const char *buf, int len, int flags) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } int win32_sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } int win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } int win32_shutdown(SOCKET s, int how) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } int win32_closesocket(SOCKET s) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s))); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } void @@ -563,6 +726,7 @@ convert_proto_info_w2a(WSAPROTOCOL_INFOW *in, WSAPROTOCOL_INFOA *out) SOCKET open_ifs_socket(int af, int type, int protocol) { +#ifndef WIN32_NO_SOCKETS dTHX; char *s; unsigned long proto_buffers_len = 0; @@ -613,13 +777,21 @@ open_ifs_socket(int af, int type, int protocol) } return out; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return INVALID_SOCKET; +#endif } SOCKET win32_socket(int af, int type, int protocol) { +#ifndef WIN32_NO_SOCKETS SOCKET s; + StartSockets(); + if((s = open_ifs_socket(af, type, protocol)) == INVALID_SOCKET) { int wsaerr = WSAGetLastError(); @@ -630,56 +802,92 @@ win32_socket(int af, int type, int protocol) s = OPEN_SOCKET(s); return s; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return INVALID_SOCKET; +#endif } struct hostent * win32_gethostbyaddr(const char *addr, int len, int type) { +#ifndef WIN32_NO_SOCKETS struct hostent *r; SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return NULL; +#endif } struct hostent * win32_gethostbyname(const char *name) { +#ifndef WIN32_NO_SOCKETS struct hostent *r; SOCKET_TEST(r = gethostbyname(name), NULL); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return NULL; +#endif } int win32_gethostname(char *name, int len) { +#ifndef WIN32_NO_SOCKETS int r; SOCKET_TEST_ERROR(r = gethostname(name, len)); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#endif } struct protoent * win32_getprotobyname(const char *name) { +#ifndef WIN32_NO_SOCKETS struct protoent *r; SOCKET_TEST(r = getprotobyname(name), NULL); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return NULL; +#endif } struct protoent * win32_getprotobynumber(int num) { +#ifndef WIN32_NO_SOCKETS struct protoent *r; SOCKET_TEST(r = getprotobynumber(num), NULL); return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return NULL; +#endif } struct servent * win32_getservbyname(const char *name, const char *proto) { +#ifndef WIN32_NO_SOCKETS dTHXa(NULL); struct servent *r; @@ -689,11 +897,17 @@ win32_getservbyname(const char *name, const char *proto) r = win32_savecopyservent(&w32_servent, r, proto); } return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return NULL; +#endif } struct servent * win32_getservbyport(int port, const char *proto) { +#ifndef WIN32_NO_SOCKETS dTHXa(NULL); struct servent *r; @@ -703,14 +917,30 @@ win32_getservbyport(int port, const char *proto) r = win32_savecopyservent(&w32_servent, r, proto); } return r; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return NULL; +#endif } int win32_ioctl(int i, unsigned int u, char *data) { +#ifdef WIN32_NO_SOCKETS + + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return SOCKET_ERROR; +#else u_long u_long_arg; int retval; + if (!wsock_started) { + Perl_croak_nocontext("ioctl implemented only on sockets"); + /* NOTREACHED */ + } + /* mauke says using memcpy avoids alignment issues */ memcpy(&u_long_arg, data, sizeof u_long_arg); retval = ioctlsocket(TO_SOCKET(i), (long)u, &u_long_arg); @@ -727,18 +957,33 @@ win32_ioctl(int i, unsigned int u, char *data) SetLastError(wsaerr); } return retval; +#endif } char FAR * win32_inet_ntoa(struct in_addr in) { +#ifndef WIN32_NO_SOCKETS + StartSockets(); return inet_ntoa(in); +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return NULL; +#endif } unsigned long win32_inet_addr(const char FAR *cp) { +#ifndef WIN32_NO_SOCKETS + StartSockets(); return inet_addr(cp); +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + errno = ENOSYS; + return -1; +#endif } /*