This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix compilation errors in win32.c with MinGW/gcc -xc++
[perl5.git] / win32 / win32sck.c
CommitLineData
326b05e3 1/* win32sck.c
68dc0745 2 *
3 * (c) 1995 Microsoft Corporation. All rights reserved.
0d130a44 4 * Developed by hip communications inc.
68dc0745 5 * Portions (c) 1993 Intergraph Corporation. All rights reserved.
6 *
7 * You may distribute under the terms of either the GNU General Public
8 * License or the Artistic License, as specified in the README file.
9 */
0a753a76 10
390b85e7 11#define WIN32IO_IS_STDIO
55d25626 12#define WIN32SCK_IS_STDSCK
0a753a76 13#define WIN32_LEAN_AND_MEAN
8fada4f6 14#define PERLIO_NOT_STDIO 0
a835ef8a
NIS
15#ifdef __GNUC__
16#define Win32_Winsock
17#endif
390b85e7 18#include <windows.h>
036c1c1e
SH
19#include <ws2spi.h>
20
0a753a76 21#include "EXTERN.h"
22#include "perl.h"
c69f6586 23
58a50f62 24#include "Win32iop.h"
0a753a76 25#include <sys/socket.h>
26#include <fcntl.h>
27#include <sys/stat.h>
28#include <assert.h>
390b85e7 29#include <io.h>
0a753a76 30
68dc0745 31/* thanks to Beverly Brown (beverly@datacube.com) */
72e6b643
SH
32#define OPEN_SOCKET(x) win32_open_osfhandle(x,O_RDWR|O_BINARY)
33#define TO_SOCKET(x) _get_osfhandle(x)
0a753a76 34
326b05e3
GS
35#define StartSockets() \
36 STMT_START { \
37 if (!wsock_started) \
38 start_sockets(); \
39 } STMT_END
40
326b05e3
GS
41#define SOCKET_TEST(x, y) \
42 STMT_START { \
43 StartSockets(); \
44 if((x) == (y)) \
b0ba2190 45 errno = get_last_socket_error(); \
326b05e3
GS
46 } STMT_END
47
48#define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
49
c9beaf97 50static int get_last_socket_error(void);
137443ea 51static struct servent* win32_savecopyservent(struct servent*d,
52 struct servent*s,
53 const char *proto);
0a753a76 54
326b05e3 55static int wsock_started = 0;
68dc0745 56
b47a847f
DD
57#ifdef WIN32_DYN_IOINFO_SIZE
58EXTERN_C Size_t w32_ioinfo_size;
59#endif
60
b73db59c
GS
61EXTERN_C void
62EndSockets(void)
63{
64 if (wsock_started)
65 WSACleanup();
66}
67
d31f3d60
SH
68/* Translate WSAExxx values to corresponding Exxx values where possible. Not all
69 * WSAExxx constants have corresponding Exxx constants in <errno.h> (even in
70 * VC++ 2010 and above, which have expanded <errno.h> with more values), but
71 * most missing constants are provided by win32/include/sys/errno2.h. The few
72 * that are not are returned unchanged.
73 *
c9beaf97
SH
74 * The list of possible WSAExxx values used here comes from the MSDN page
75 * titled "Windows Sockets Error Codes".
d31f3d60 76 *
c9beaf97
SH
77 * (Note: Only the WSAExxx values are handled here; other WSAxxx values are
78 * returned unchanged. The return value normally ends up in errno/$! and at
79 * the Perl code level may be tested against the Exxx constants exported by
80 * the Errno and POSIX modules, which have never handled the other WSAxxx
81 * values themselves, apparently without any ill effect so far.)
82 */
83int
84convert_wsa_error_to_errno(int wsaerr)
85{
86 switch (wsaerr) {
b0ba2190
SH
87 case WSAEINTR:
88 return EINTR;
89 case WSAEBADF:
90 return EBADF;
91 case WSAEACCES:
92 return EACCES;
93 case WSAEFAULT:
94 return EFAULT;
95 case WSAEINVAL:
96 return EINVAL;
97 case WSAEMFILE:
98 return EMFILE;
99 case WSAEWOULDBLOCK:
100 return EWOULDBLOCK;
101 case WSAEINPROGRESS:
102 return EINPROGRESS;
103 case WSAEALREADY:
104 return EALREADY;
105 case WSAENOTSOCK:
106 return ENOTSOCK;
107 case WSAEDESTADDRREQ:
108 return EDESTADDRREQ;
109 case WSAEMSGSIZE:
110 return EMSGSIZE;
111 case WSAEPROTOTYPE:
112 return EPROTOTYPE;
113 case WSAENOPROTOOPT:
114 return ENOPROTOOPT;
115 case WSAEPROTONOSUPPORT:
116 return EPROTONOSUPPORT;
117 case WSAESOCKTNOSUPPORT:
118 return ESOCKTNOSUPPORT;
119 case WSAEOPNOTSUPP:
120 return EOPNOTSUPP;
121 case WSAEPFNOSUPPORT:
122 return EPFNOSUPPORT;
123 case WSAEAFNOSUPPORT:
124 return EAFNOSUPPORT;
125 case WSAEADDRINUSE:
126 return EADDRINUSE;
127 case WSAEADDRNOTAVAIL:
128 return EADDRNOTAVAIL;
129 case WSAENETDOWN:
130 return ENETDOWN;
131 case WSAENETUNREACH:
132 return ENETUNREACH;
133 case WSAENETRESET:
134 return ENETRESET;
135 case WSAECONNABORTED:
136 return ECONNABORTED;
137 case WSAECONNRESET:
138 return ECONNRESET;
139 case WSAENOBUFS:
140 return ENOBUFS;
141 case WSAEISCONN:
142 return EISCONN;
143 case WSAENOTCONN:
144 return ENOTCONN;
145 case WSAESHUTDOWN:
146 return ESHUTDOWN;
147 case WSAETOOMANYREFS:
148 return ETOOMANYREFS;
149 case WSAETIMEDOUT:
150 return ETIMEDOUT;
151 case WSAECONNREFUSED:
152 return ECONNREFUSED;
153 case WSAELOOP:
154 return ELOOP;
155 case WSAENAMETOOLONG:
156 return ENAMETOOLONG;
157 case WSAEHOSTDOWN:
d31f3d60 158 return WSAEHOSTDOWN; /* EHOSTDOWN is not defined */
b0ba2190
SH
159 case WSAEHOSTUNREACH:
160 return EHOSTUNREACH;
161 case WSAENOTEMPTY:
162 return ENOTEMPTY;
163 case WSAEPROCLIM:
164 return EPROCLIM;
165 case WSAEUSERS:
166 return EUSERS;
167 case WSAEDQUOT:
168 return EDQUOT;
169 case WSAESTALE:
170 return ESTALE;
171 case WSAEREMOTE:
172 return EREMOTE;
173 case WSAEDISCON:
d31f3d60 174 return WSAEDISCON; /* EDISCON is not defined */
b0ba2190 175 case WSAENOMORE:
d31f3d60 176 return WSAENOMORE; /* ENOMORE is not defined */
4eaf3102
SH
177#ifdef WSAECANCELLED
178 case WSAECANCELLED: /* New in WinSock2 */
cd6a3131 179 return ECANCELED;
4eaf3102 180#endif
b0ba2190 181 case WSAEINVALIDPROCTABLE:
d31f3d60 182 return WSAEINVALIDPROCTABLE; /* EINVALIDPROCTABLE is not defined */
b0ba2190 183 case WSAEINVALIDPROVIDER:
d31f3d60 184 return WSAEINVALIDPROVIDER; /* EINVALIDPROVIDER is not defined */
b0ba2190 185 case WSAEPROVIDERFAILEDINIT:
d31f3d60 186 return WSAEPROVIDERFAILEDINIT; /* EPROVIDERFAILEDINIT is not defined */
b0ba2190 187 case WSAEREFUSED:
d31f3d60 188 return WSAEREFUSED; /* EREFUSED is not defined */
b0ba2190
SH
189 }
190
c9beaf97 191 return wsaerr;
b0ba2190
SH
192}
193
e85fa3eb 194#ifdef ERRNO_HAS_POSIX_SUPPLEMENT
cd6a3131
SH
195/* Translate Exxx values in the POSIX supplement range defined in VC++ 2010 and
196 * above (EADDRINUSE <= err <= EWOULDBLOCK) to corresponding WSAExxx values. Not
4eaf3102 197 * all such Exxx constants have corresponding WSAExxx constants in <winsock*.h>;
cd6a3131 198 * we just use ERROR_INVALID_FUNCTION for those that are missing but do not
e85fa3eb
SH
199 * really expect to encounter them anyway in the context in which this function
200 * is called.
4f79e9b1
SH
201 * Some versions of MinGW/gcc-4.8 and above also define most, but not all, of
202 * these extra Exxx values. The missing ones are all cases for which there is no
203 * corresponding WSAExxx constant anyway, so we simply omit the cases for them
204 * here.
cd6a3131
SH
205 * Other Exxx values (err < sys_nerr) are returned unchanged.
206 */
207int
208convert_errno_to_wsa_error(int err)
209{
210 switch (err) {
211 case EADDRINUSE:
212 return WSAEADDRINUSE;
213 case EADDRNOTAVAIL:
214 return WSAEADDRNOTAVAIL;
215 case EAFNOSUPPORT:
216 return WSAEAFNOSUPPORT;
217 case EALREADY:
218 return WSAEALREADY;
4f79e9b1
SH
219#ifdef EBADMSG
220 case EBADMSG: /* Not defined in gcc-4.8.0 */
cd6a3131 221 return ERROR_INVALID_FUNCTION;
4f79e9b1 222#endif
cd6a3131 223 case ECANCELED:
4eaf3102
SH
224#ifdef WSAECANCELLED
225 return WSAECANCELLED; /* New in WinSock2 */
226#else
227 return ERROR_INVALID_FUNCTION;
228#endif
cd6a3131
SH
229 case ECONNABORTED:
230 return WSAECONNABORTED;
231 case ECONNREFUSED:
232 return WSAECONNREFUSED;
233 case ECONNRESET:
234 return WSAECONNRESET;
235 case EDESTADDRREQ:
236 return WSAEDESTADDRREQ;
237 case EHOSTUNREACH:
238 return WSAEHOSTUNREACH;
4f79e9b1
SH
239#ifdef EIDRM
240 case EIDRM: /* Not defined in gcc-4.8.0 */
cd6a3131 241 return ERROR_INVALID_FUNCTION;
4f79e9b1 242#endif
cd6a3131
SH
243 case EINPROGRESS:
244 return WSAEINPROGRESS;
245 case EISCONN:
246 return WSAEISCONN;
247 case ELOOP:
248 return WSAELOOP;
249 case EMSGSIZE:
250 return WSAEMSGSIZE;
251 case ENETDOWN:
252 return WSAENETDOWN;
253 case ENETRESET:
254 return WSAENETRESET;
255 case ENETUNREACH:
256 return WSAENETUNREACH;
257 case ENOBUFS:
258 return WSAENOBUFS;
4f79e9b1
SH
259#ifdef ENODATA
260 case ENODATA: /* Not defined in gcc-4.8.0 */
cd6a3131 261 return ERROR_INVALID_FUNCTION;
4f79e9b1
SH
262#endif
263#ifdef ENOLINK
264 case ENOLINK: /* Not defined in gcc-4.8.0 */
cd6a3131 265 return ERROR_INVALID_FUNCTION;
4f79e9b1
SH
266#endif
267#ifdef ENOMSG
268 case ENOMSG: /* Not defined in gcc-4.8.0 */
cd6a3131 269 return ERROR_INVALID_FUNCTION;
4f79e9b1 270#endif
cd6a3131
SH
271 case ENOPROTOOPT:
272 return WSAENOPROTOOPT;
4f79e9b1
SH
273#ifdef ENOSR
274 case ENOSR: /* Not defined in gcc-4.8.0 */
cd6a3131 275 return ERROR_INVALID_FUNCTION;
4f79e9b1
SH
276#endif
277#ifdef ENOSTR
278 case ENOSTR: /* Not defined in gcc-4.8.0 */
cd6a3131 279 return ERROR_INVALID_FUNCTION;
4f79e9b1 280#endif
cd6a3131
SH
281 case ENOTCONN:
282 return WSAENOTCONN;
4f79e9b1
SH
283#ifdef ENOTRECOVERABLE
284 case ENOTRECOVERABLE: /* Not defined in gcc-4.8.0 */
cd6a3131 285 return ERROR_INVALID_FUNCTION;
4f79e9b1 286#endif
cd6a3131
SH
287 case ENOTSOCK:
288 return WSAENOTSOCK;
289 case ENOTSUP:
290 return ERROR_INVALID_FUNCTION;
291 case EOPNOTSUPP:
292 return WSAEOPNOTSUPP;
4f79e9b1
SH
293#ifdef EOTHER
294 case EOTHER: /* Not defined in gcc-4.8.0 */
cd6a3131 295 return ERROR_INVALID_FUNCTION;
4f79e9b1 296#endif
cd6a3131
SH
297 case EOVERFLOW:
298 return ERROR_INVALID_FUNCTION;
299 case EOWNERDEAD:
300 return ERROR_INVALID_FUNCTION;
301 case EPROTO:
302 return ERROR_INVALID_FUNCTION;
303 case EPROTONOSUPPORT:
304 return WSAEPROTONOSUPPORT;
305 case EPROTOTYPE:
306 return WSAEPROTOTYPE;
4f79e9b1
SH
307#ifdef ETIME
308 case ETIME: /* Not defined in gcc-4.8.0 */
cd6a3131 309 return ERROR_INVALID_FUNCTION;
4f79e9b1 310#endif
cd6a3131
SH
311 case ETIMEDOUT:
312 return WSAETIMEDOUT;
4f79e9b1
SH
313#ifdef ETXTBSY
314 case ETXTBSY: /* Not defined in gcc-4.8.0 */
cd6a3131 315 return ERROR_INVALID_FUNCTION;
4f79e9b1 316#endif
cd6a3131
SH
317 case EWOULDBLOCK:
318 return WSAEWOULDBLOCK;
319 }
320
321 return err;
322}
e85fa3eb 323#endif /* ERRNO_HAS_POSIX_SUPPLEMENT */
cd6a3131
SH
324
325static int
326get_last_socket_error(void)
327{
328 return convert_wsa_error_to_errno(WSAGetLastError());
329}
330
68dc0745 331void
326b05e3 332start_sockets(void)
68dc0745 333{
334 unsigned short version;
335 WSADATA retdata;
336 int ret;
68dc0745 337
68dc0745 338 /*
339 * initalize the winsock interface and insure that it is
340 * cleaned up at exit.
341 */
036c1c1e 342 version = 0x2;
326b05e3 343 if(ret = WSAStartup(version, &retdata))
4f63d024 344 Perl_croak_nocontext("Unable to locate winsock library!\n");
68dc0745 345 if(retdata.wVersion != version)
036c1c1e 346 Perl_croak_nocontext("Could not find version 2.0 of winsock dll\n");
68dc0745 347
348 /* atexit((void (*)(void)) EndSockets); */
401ef382
SN
349 wsock_started = 1;
350}
0a753a76 351
36bb5e1d
NC
352/* in no sockets Win32 builds, these use the inline functions defined in
353 * perl.h
19253ae6 354 */
68dc0745 355u_long
356win32_htonl(u_long hostlong)
0a753a76 357{
36bb5e1d 358#ifndef WIN32_NO_SOCKETS
326b05e3 359 StartSockets();
19253ae6 360#endif
326b05e3 361 return htonl(hostlong);
0a753a76 362}
363
68dc0745 364u_short
365win32_htons(u_short hostshort)
0a753a76 366{
36bb5e1d 367#ifndef WIN32_NO_SOCKETS
326b05e3 368 StartSockets();
19253ae6 369#endif
326b05e3 370 return htons(hostshort);
0a753a76 371}
372
68dc0745 373u_long
374win32_ntohl(u_long netlong)
0a753a76 375{
36bb5e1d 376#ifndef WIN32_NO_SOCKETS
326b05e3 377 StartSockets();
19253ae6 378#endif
326b05e3 379 return ntohl(netlong);
0a753a76 380}
381
68dc0745 382u_short
383win32_ntohs(u_short netshort)
0a753a76 384{
36bb5e1d 385#ifndef WIN32_NO_SOCKETS
326b05e3 386 StartSockets();
19253ae6 387#endif
326b05e3 388 return ntohs(netshort);
0a753a76 389}
390
391
0a753a76 392
68dc0745 393SOCKET
394win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 395{
68dc0745 396 SOCKET r;
0a753a76 397
326b05e3 398 SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
68dc0745 399 return OPEN_SOCKET(r);
0a753a76 400}
401
68dc0745 402int
403win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen)
0a753a76 404{
68dc0745 405 int r;
0a753a76 406
326b05e3 407 SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen));
68dc0745 408 return r;
0a753a76 409}
410
68dc0745 411int
412win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
0a753a76 413{
68dc0745 414 int r;
0a753a76 415
326b05e3 416 SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen));
68dc0745 417 return r;
0a753a76 418}
419
420
68dc0745 421int
422win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 423{
68dc0745 424 int r;
0a753a76 425
326b05e3 426 SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen));
68dc0745 427 return r;
0a753a76 428}
429
68dc0745 430int
431win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 432{
68dc0745 433 int r;
0a753a76 434
326b05e3 435 SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen));
68dc0745 436 return r;
0a753a76 437}
438
68dc0745 439int
440win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen)
0a753a76 441{
68dc0745 442 int r;
0a753a76 443
326b05e3 444 SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen));
68dc0745 445 return r;
0a753a76 446}
447
2d7a9237 448int
68dc0745 449win32_ioctlsocket(SOCKET s, long cmd, u_long *argp)
0a753a76 450{
68dc0745 451 int r;
0a753a76 452
326b05e3 453 SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp));
68dc0745 454 return r;
0a753a76 455}
456
68dc0745 457int
458win32_listen(SOCKET s, int backlog)
0a753a76 459{
68dc0745 460 int r;
0a753a76 461
326b05e3 462 SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog));
68dc0745 463 return r;
0a753a76 464}
465
68dc0745 466int
467win32_recv(SOCKET s, char *buf, int len, int flags)
0a753a76 468{
68dc0745 469 int r;
0a753a76 470
326b05e3 471 SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags));
68dc0745 472 return r;
0a753a76 473}
474
68dc0745 475int
476win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
0a753a76 477{
68dc0745 478 int r;
e4449fe1 479 int frombufsize = *fromlen;
0a753a76 480
326b05e3 481 SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen));
e4449fe1
GS
482 /* Winsock's recvfrom() only returns a valid 'from' when the socket
483 * is connectionless. Perl expects a valid 'from' for all types
484 * of sockets, so go the extra mile.
485 */
486 if (r != SOCKET_ERROR && frombufsize == *fromlen)
487 (void)win32_getpeername(s, from, fromlen);
68dc0745 488 return r;
0a753a76 489}
490
68dc0745 491/* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */
492int
55d25626 493win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout)
0a753a76 494{
55d25626 495 int r;
3ead22cb 496 int i, fd, save_errno = errno;
8dc00b2f 497 FD_SET nrd, nwr, nex;
e4d771f5 498 bool just_sleep = TRUE;
0a753a76 499
f2bb5751 500 StartSockets();
0a753a76 501
68dc0745 502 FD_ZERO(&nrd);
503 FD_ZERO(&nwr);
504 FD_ZERO(&nex);
505 for (i = 0; i < nfds; i++) {
f7bbabd3
JD
506 if (rd && PERL_FD_ISSET(i,rd)) {
507 fd = TO_SOCKET(i);
47660177 508 FD_SET((unsigned)fd, &nrd);
e4d771f5 509 just_sleep = FALSE;
f7bbabd3
JD
510 }
511 if (wr && PERL_FD_ISSET(i,wr)) {
512 fd = TO_SOCKET(i);
47660177 513 FD_SET((unsigned)fd, &nwr);
e4d771f5 514 just_sleep = FALSE;
f7bbabd3
JD
515 }
516 if (ex && PERL_FD_ISSET(i,ex)) {
517 fd = TO_SOCKET(i);
47660177 518 FD_SET((unsigned)fd, &nex);
e4d771f5 519 just_sleep = FALSE;
f7bbabd3 520 }
68dc0745 521 }
522
e4d771f5
JD
523 /* winsock seems incapable of dealing with all three fd_sets being empty,
524 * so do the (millisecond) sleep as a special case
525 */
526 if (just_sleep) {
527 if (timeout)
528 Sleep(timeout->tv_sec * 1000 +
529 timeout->tv_usec / 1000); /* do the best we can */
530 else
531 Sleep(UINT_MAX);
532 return 0;
533 }
534
1c878075 535 errno = save_errno;
8dc00b2f 536 SOCKET_TEST_ERROR(r = select(nfds, &nrd, &nwr, &nex, timeout));
1c878075 537 save_errno = errno;
0a753a76 538
68dc0745 539 for (i = 0; i < nfds; i++) {
f7bbabd3
JD
540 if (rd && PERL_FD_ISSET(i,rd)) {
541 fd = TO_SOCKET(i);
542 if (!FD_ISSET(fd, &nrd))
543 PERL_FD_CLR(i,rd);
544 }
545 if (wr && PERL_FD_ISSET(i,wr)) {
546 fd = TO_SOCKET(i);
547 if (!FD_ISSET(fd, &nwr))
548 PERL_FD_CLR(i,wr);
549 }
550 if (ex && PERL_FD_ISSET(i,ex)) {
551 fd = TO_SOCKET(i);
552 if (!FD_ISSET(fd, &nex))
553 PERL_FD_CLR(i,ex);
554 }
68dc0745 555 }
1c878075 556 errno = save_errno;
68dc0745 557 return r;
0a753a76 558}
559
68dc0745 560int
561win32_send(SOCKET s, const char *buf, int len, int flags)
0a753a76 562{
68dc0745 563 int r;
0a753a76 564
326b05e3 565 SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags));
68dc0745 566 return r;
0a753a76 567}
568
68dc0745 569int
570win32_sendto(SOCKET s, const char *buf, int len, int flags,
571 const struct sockaddr *to, int tolen)
0a753a76 572{
68dc0745 573 int r;
0a753a76 574
326b05e3 575 SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen));
68dc0745 576 return r;
0a753a76 577}
578
68dc0745 579int
580win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
0a753a76 581{
68dc0745 582 int r;
0a753a76 583
326b05e3 584 SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen));
68dc0745 585 return r;
0a753a76 586}
587
68dc0745 588int
589win32_shutdown(SOCKET s, int how)
0a753a76 590{
68dc0745 591 int r;
0a753a76 592
326b05e3 593 SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how));
68dc0745 594 return r;
0a753a76 595}
596
3a25acb4
GS
597int
598win32_closesocket(SOCKET s)
599{
600 int r;
601
602 SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s)));
603 return r;
604}
605
036c1c1e
SH
606void
607convert_proto_info_w2a(WSAPROTOCOL_INFOW *in, WSAPROTOCOL_INFOA *out)
608{
609 Copy(in, out, 1, WSAPROTOCOL_INFOA);
610 wcstombs(out->szProtocol, in->szProtocol, sizeof(out->szProtocol));
611}
612
613SOCKET
614open_ifs_socket(int af, int type, int protocol)
615{
1c972609
SH
616 dTHX;
617 char *s;
036c1c1e
SH
618 unsigned long proto_buffers_len = 0;
619 int error_code;
620 SOCKET out = INVALID_SOCKET;
621
1c972609
SH
622 if ((s = PerlEnv_getenv("PERL_ALLOW_NON_IFS_LSP")) && atoi(s))
623 return WSASocket(af, type, protocol, NULL, 0, 0);
624
036c1c1e
SH
625 if (WSCEnumProtocols(NULL, NULL, &proto_buffers_len, &error_code) == SOCKET_ERROR
626 && error_code == WSAENOBUFS)
627 {
628 WSAPROTOCOL_INFOW *proto_buffers;
629 int protocols_available = 0;
630
a02a5408 631 Newx(proto_buffers, proto_buffers_len / sizeof(WSAPROTOCOL_INFOW),
036c1c1e
SH
632 WSAPROTOCOL_INFOW);
633
634 if ((protocols_available = WSCEnumProtocols(NULL, proto_buffers,
635 &proto_buffers_len, &error_code)) != SOCKET_ERROR)
636 {
637 int i;
638 for (i = 0; i < protocols_available; i++)
639 {
640 WSAPROTOCOL_INFOA proto_info;
641
642 if ((af != AF_UNSPEC && af != proto_buffers[i].iAddressFamily)
643 || (type != proto_buffers[i].iSocketType)
f9169742
SH
644 || (protocol != 0 && proto_buffers[i].iProtocol != 0 &&
645 protocol != proto_buffers[i].iProtocol))
036c1c1e
SH
646 continue;
647
648 if ((proto_buffers[i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0)
649 continue;
650
651 convert_proto_info_w2a(&(proto_buffers[i]), &proto_info);
652
653 out = WSASocket(af, type, protocol, &proto_info, 0, 0);
654 break;
655 }
656 }
657
658 Safefree(proto_buffers);
659 }
660
661 return out;
662}
663
68dc0745 664SOCKET
665win32_socket(int af, int type, int protocol)
0a753a76 666{
68dc0745 667 SOCKET s;
0a753a76 668
3a25acb4 669 StartSockets();
036c1c1e 670
72e6b643 671 if((s = open_ifs_socket(af, type, protocol)) == INVALID_SOCKET)
b0ba2190 672 errno = get_last_socket_error();
68dc0745 673 else
674 s = OPEN_SOCKET(s);
0a753a76 675
68dc0745 676 return s;
0a753a76 677}
678
00b02797
JH
679/*
680 * close RTL fd while respecting sockets
681 * added as temporary measure until PerlIO has real
682 * Win32 native layer
683 * -- BKS, 11-11-2000
684*/
685
686int my_close(int fd)
687{
688 int osf;
689 if (!wsock_started) /* No WinSock? */
690 return(close(fd)); /* Then not a socket. */
691 osf = TO_SOCKET(fd);/* Get it now before it's gone! */
692 if (osf != -1) {
693 int err;
694 err = closesocket(osf);
695 if (err == 0) {
b47a847f
DD
696 assert(_osfhnd(fd) == osf); /* catch a bad ioinfo struct def */
697 /* don't close freed handle */
698 _set_osfhnd(fd, INVALID_HANDLE_VALUE);
699 return close(fd);
00b02797
JH
700 }
701 else if (err == SOCKET_ERROR) {
b0ba2190
SH
702 err = get_last_socket_error();
703 if (err != ENOTSOCK) {
00b02797
JH
704 (void)close(fd);
705 errno = err;
706 return EOF;
707 }
708 }
709 }
710 return close(fd);
711}
712
fb73857a 713#undef fclose
714int
715my_fclose (FILE *pf)
716{
4e945249 717 int osf;
326b05e3
GS
718 if (!wsock_started) /* No WinSock? */
719 return(fclose(pf)); /* Then not a socket. */
00b02797 720 osf = TO_SOCKET(win32_fileno(pf));/* Get it now before it's gone! */
d3d49e29
GS
721 if (osf != -1) {
722 int err;
723 win32_fflush(pf);
724 err = closesocket(osf);
725 if (err == 0) {
b47a847f
DD
726 assert(_osfhnd(win32_fileno(pf)) == osf); /* catch a bad ioinfo struct def */
727 /* don't close freed handle */
728 _set_osfhnd(win32_fileno(pf), INVALID_HANDLE_VALUE);
729 return fclose(pf);
d3d49e29
GS
730 }
731 else if (err == SOCKET_ERROR) {
b0ba2190
SH
732 err = get_last_socket_error();
733 if (err != ENOTSOCK) {
d3d49e29
GS
734 (void)fclose(pf);
735 errno = err;
736 return EOF;
737 }
738 }
326b05e3 739 }
d3d49e29 740 return fclose(pf);
fb73857a 741}
742
68dc0745 743struct hostent *
744win32_gethostbyaddr(const char *addr, int len, int type)
0a753a76 745{
68dc0745 746 struct hostent *r;
0a753a76 747
326b05e3 748 SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL);
68dc0745 749 return r;
0a753a76 750}
751
68dc0745 752struct hostent *
753win32_gethostbyname(const char *name)
0a753a76 754{
68dc0745 755 struct hostent *r;
0a753a76 756
326b05e3 757 SOCKET_TEST(r = gethostbyname(name), NULL);
68dc0745 758 return r;
0a753a76 759}
760
68dc0745 761int
762win32_gethostname(char *name, int len)
0a753a76 763{
68dc0745 764 int r;
0a753a76 765
326b05e3 766 SOCKET_TEST_ERROR(r = gethostname(name, len));
68dc0745 767 return r;
0a753a76 768}
769
68dc0745 770struct protoent *
771win32_getprotobyname(const char *name)
0a753a76 772{
68dc0745 773 struct protoent *r;
0a753a76 774
326b05e3 775 SOCKET_TEST(r = getprotobyname(name), NULL);
68dc0745 776 return r;
0a753a76 777}
778
68dc0745 779struct protoent *
780win32_getprotobynumber(int num)
0a753a76 781{
68dc0745 782 struct protoent *r;
0a753a76 783
326b05e3 784 SOCKET_TEST(r = getprotobynumber(num), NULL);
68dc0745 785 return r;
0a753a76 786}
787
68dc0745 788struct servent *
789win32_getservbyname(const char *name, const char *proto)
0a753a76 790{
04a2c3d9 791 dTHXa(NULL);
68dc0745 792 struct servent *r;
c53bd28a 793
326b05e3 794 SOCKET_TEST(r = getservbyname(name, proto), NULL);
68dc0745 795 if (r) {
04a2c3d9 796 aTHXa(PERL_GET_THX);
3352bfcb 797 r = win32_savecopyservent(&w32_servent, r, proto);
68dc0745 798 }
799 return r;
0a753a76 800}
801
68dc0745 802struct servent *
803win32_getservbyport(int port, const char *proto)
0a753a76 804{
04a2c3d9 805 dTHXa(NULL);
68dc0745 806 struct servent *r;
0a753a76 807
326b05e3 808 SOCKET_TEST(r = getservbyport(port, proto), NULL);
68dc0745 809 if (r) {
04a2c3d9 810 aTHXa(PERL_GET_THX);
3352bfcb 811 r = win32_savecopyservent(&w32_servent, r, proto);
68dc0745 812 }
813 return r;
0a753a76 814}
815
f998180f
GS
816int
817win32_ioctl(int i, unsigned int u, char *data)
818{
69a143a6 819 u_long u_long_arg;
f998180f 820 int retval;
69a143a6 821
f998180f 822 if (!wsock_started) {
4f63d024 823 Perl_croak_nocontext("ioctl implemented only on sockets");
f998180f
GS
824 /* NOTREACHED */
825 }
826
69a143a6
YO
827 /* mauke says using memcpy avoids alignment issues */
828 memcpy(&u_long_arg, data, sizeof u_long_arg);
829 retval = ioctlsocket(TO_SOCKET(i), (long)u, &u_long_arg);
830 memcpy(data, &u_long_arg, sizeof u_long_arg);
831
f998180f 832 if (retval == SOCKET_ERROR) {
b0ba2190
SH
833 int err = get_last_socket_error();
834 if (err == ENOTSOCK) {
4f63d024 835 Perl_croak_nocontext("ioctl implemented only on sockets");
f998180f
GS
836 /* NOTREACHED */
837 }
b0ba2190 838 errno = err;
f998180f
GS
839 }
840 return retval;
841}
842
68dc0745 843char FAR *
844win32_inet_ntoa(struct in_addr in)
0a753a76 845{
326b05e3
GS
846 StartSockets();
847 return inet_ntoa(in);
0a753a76 848}
849
68dc0745 850unsigned long
851win32_inet_addr(const char FAR *cp)
0a753a76 852{
326b05e3
GS
853 StartSockets();
854 return inet_addr(cp);
0a753a76 855}
68dc0745 856
857/*
858 * Networking stubs
859 */
0a753a76 860
68dc0745 861void
862win32_endhostent()
0a753a76 863{
073dd035 864 win32_croak_not_implemented("endhostent");
0a753a76 865}
866
68dc0745 867void
868win32_endnetent()
0a753a76 869{
073dd035 870 win32_croak_not_implemented("endnetent");
0a753a76 871}
872
68dc0745 873void
874win32_endprotoent()
0a753a76 875{
073dd035 876 win32_croak_not_implemented("endprotoent");
0a753a76 877}
878
68dc0745 879void
880win32_endservent()
0a753a76 881{
073dd035 882 win32_croak_not_implemented("endservent");
0a753a76 883}
884
885
68dc0745 886struct netent *
887win32_getnetent(void)
0a753a76 888{
073dd035 889 win32_croak_not_implemented("getnetent");
68dc0745 890 return (struct netent *) NULL;
0a753a76 891}
892
68dc0745 893struct netent *
894win32_getnetbyname(char *name)
0a753a76 895{
073dd035 896 win32_croak_not_implemented("getnetbyname");
68dc0745 897 return (struct netent *)NULL;
0a753a76 898}
899
68dc0745 900struct netent *
901win32_getnetbyaddr(long net, int type)
0a753a76 902{
073dd035 903 win32_croak_not_implemented("getnetbyaddr");
68dc0745 904 return (struct netent *)NULL;
0a753a76 905}
906
68dc0745 907struct protoent *
908win32_getprotoent(void)
0a753a76 909{
073dd035 910 win32_croak_not_implemented("getprotoent");
68dc0745 911 return (struct protoent *) NULL;
0a753a76 912}
913
68dc0745 914struct servent *
915win32_getservent(void)
0a753a76 916{
073dd035 917 win32_croak_not_implemented("getservent");
68dc0745 918 return (struct servent *) NULL;
0a753a76 919}
920
68dc0745 921void
922win32_sethostent(int stayopen)
0a753a76 923{
073dd035 924 win32_croak_not_implemented("sethostent");
0a753a76 925}
926
927
68dc0745 928void
929win32_setnetent(int stayopen)
0a753a76 930{
073dd035 931 win32_croak_not_implemented("setnetent");
0a753a76 932}
933
934
68dc0745 935void
936win32_setprotoent(int stayopen)
0a753a76 937{
073dd035 938 win32_croak_not_implemented("setprotoent");
0a753a76 939}
940
941
68dc0745 942void
943win32_setservent(int stayopen)
0a753a76 944{
073dd035 945 win32_croak_not_implemented("setservent");
0a753a76 946}
947
137443ea 948static struct servent*
949win32_savecopyservent(struct servent*d, struct servent*s, const char *proto)
950{
951 d->s_name = s->s_name;
952 d->s_aliases = s->s_aliases;
953 d->s_port = s->s_port;
8cbe99e5 954 if (s->s_proto && strlen(s->s_proto))
137443ea 955 d->s_proto = s->s_proto;
0af56dfe 956 else
c69f6586 957 if (proto && strlen(proto))
137443ea 958 d->s_proto = (char *)proto;
959 else
960 d->s_proto = "tcp";
961
962 return d;
963}
964
0a753a76 965