This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
workaround for undefined symbol
[perl5.git] / win32 / win32sck.c
CommitLineData
326b05e3 1/* win32sck.c
68dc0745 2 *
3 * (c) 1995 Microsoft Corporation. All rights reserved.
4 * Developed by hip communications inc., http://info.hip.com/info/
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
a835ef8a
NIS
14#ifdef __GNUC__
15#define Win32_Winsock
16#endif
390b85e7 17#include <windows.h>
0a753a76 18#include "EXTERN.h"
19#include "perl.h"
c69f6586
GS
20
21#if defined(PERL_OBJECT)
22#define NO_XSLOCKS
c69f6586
GS
23#include "XSUB.h"
24#endif
25
58a50f62 26#include "Win32iop.h"
0a753a76 27#include <sys/socket.h>
28#include <fcntl.h>
29#include <sys/stat.h>
30#include <assert.h>
390b85e7 31#include <io.h>
0a753a76 32
68dc0745 33/* thanks to Beverly Brown (beverly@datacube.com) */
326b05e3 34#ifdef USE_SOCKETS_AS_HANDLES
58a50f62 35# define OPEN_SOCKET(x) win32_open_osfhandle(x,O_RDWR|O_BINARY)
326b05e3 36# define TO_SOCKET(x) _get_osfhandle(x)
0a753a76 37#else
0a753a76 38# define OPEN_SOCKET(x) (x)
39# define TO_SOCKET(x) (x)
68dc0745 40#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 41
401ef382 42#ifdef USE_THREADS
326b05e3
GS
43#define StartSockets() \
44 STMT_START { \
45 if (!wsock_started) \
46 start_sockets(); \
401ef382 47 set_socktype(); \
326b05e3 48 } STMT_END
401ef382
SN
49#else
50#define StartSockets() \
51 STMT_START { \
52 if (!wsock_started) { \
53 start_sockets(); \
54 set_socktype(); \
55 } \
56 } STMT_END
57#endif
326b05e3
GS
58
59#define EndSockets() \
60 STMT_START { \
61 if (wsock_started) \
62 WSACleanup(); \
63 } STMT_END
64
65#define SOCKET_TEST(x, y) \
66 STMT_START { \
67 StartSockets(); \
68 if((x) == (y)) \
69 errno = WSAGetLastError(); \
70 } STMT_END
71
72#define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
73
137443ea 74static struct servent* win32_savecopyservent(struct servent*d,
75 struct servent*s,
76 const char *proto);
0a753a76 77
326b05e3 78static int wsock_started = 0;
68dc0745 79
80void
326b05e3 81start_sockets(void)
68dc0745 82{
c5be433b 83 dTHXo;
68dc0745 84 unsigned short version;
85 WSADATA retdata;
86 int ret;
68dc0745 87
68dc0745 88 /*
89 * initalize the winsock interface and insure that it is
90 * cleaned up at exit.
91 */
92 version = 0x101;
326b05e3 93 if(ret = WSAStartup(version, &retdata))
4f63d024 94 Perl_croak_nocontext("Unable to locate winsock library!\n");
68dc0745 95 if(retdata.wVersion != version)
4f63d024 96 Perl_croak_nocontext("Could not find version 1.1 of winsock dll\n");
68dc0745 97
98 /* atexit((void (*)(void)) EndSockets); */
401ef382
SN
99 wsock_started = 1;
100}
0a753a76 101
401ef382
SN
102void
103set_socktype(void)
104{
0a753a76 105#ifdef USE_SOCKETS_AS_HANDLES
401ef382 106#ifdef USE_THREADS
4f63d024 107 dTHX;
3352bfcb 108 if (!w32_init_socktype) {
401ef382 109#endif
3352bfcb
GS
110 int iSockOpt = SO_SYNCHRONOUS_NONALERT;
111 /*
112 * Enable the use of sockets as filehandles
113 */
114 setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
115 (char *)&iSockOpt, sizeof(iSockOpt));
401ef382 116#ifdef USE_THREADS
3352bfcb 117 w32_init_socktype = 1;
401ef382
SN
118 }
119#endif
68dc0745 120#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 121}
122
123
124#ifndef USE_SOCKETS_AS_HANDLES
f3986ebb 125#undef fdopen
68dc0745 126FILE *
f3986ebb 127my_fdopen(int fd, char *mode)
0a753a76 128{
68dc0745 129 FILE *fp;
130 char sockbuf[256];
131 int optlen = sizeof(sockbuf);
132 int retval;
0a753a76 133
326b05e3 134 if (!wsock_started)
fb73857a 135 return(fdopen(fd, mode));
0a753a76 136
326b05e3
GS
137 retval = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
138 if(retval == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) {
fb73857a 139 return(fdopen(fd, mode));
68dc0745 140 }
0a753a76 141
68dc0745 142 /*
143 * If we get here, then fd is actually a socket.
144 */
fc36a67e 145 Newz(1310, fp, 1, FILE);
68dc0745 146 if(fp == NULL) {
147 errno = ENOMEM;
148 return NULL;
149 }
0a753a76 150
68dc0745 151 fp->_file = fd;
152 if(*mode == 'r')
153 fp->_flag = _IOREAD;
154 else
155 fp->_flag = _IOWRT;
156
157 return fp;
0a753a76 158}
68dc0745 159#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 160
161
68dc0745 162u_long
163win32_htonl(u_long hostlong)
0a753a76 164{
326b05e3
GS
165 StartSockets();
166 return htonl(hostlong);
0a753a76 167}
168
68dc0745 169u_short
170win32_htons(u_short hostshort)
0a753a76 171{
326b05e3
GS
172 StartSockets();
173 return htons(hostshort);
0a753a76 174}
175
68dc0745 176u_long
177win32_ntohl(u_long netlong)
0a753a76 178{
326b05e3
GS
179 StartSockets();
180 return ntohl(netlong);
0a753a76 181}
182
68dc0745 183u_short
184win32_ntohs(u_short netshort)
0a753a76 185{
326b05e3
GS
186 StartSockets();
187 return ntohs(netshort);
0a753a76 188}
189
190
0a753a76 191
68dc0745 192SOCKET
193win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 194{
68dc0745 195 SOCKET r;
0a753a76 196
326b05e3 197 SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
68dc0745 198 return OPEN_SOCKET(r);
0a753a76 199}
200
68dc0745 201int
202win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen)
0a753a76 203{
68dc0745 204 int r;
0a753a76 205
326b05e3 206 SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen));
68dc0745 207 return r;
0a753a76 208}
209
68dc0745 210int
211win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
0a753a76 212{
68dc0745 213 int r;
0a753a76 214
326b05e3 215 SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen));
68dc0745 216 return r;
0a753a76 217}
218
219
68dc0745 220int
221win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 222{
68dc0745 223 int r;
0a753a76 224
326b05e3 225 SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen));
68dc0745 226 return r;
0a753a76 227}
228
68dc0745 229int
230win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 231{
68dc0745 232 int r;
0a753a76 233
326b05e3 234 SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen));
68dc0745 235 return r;
0a753a76 236}
237
68dc0745 238int
239win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen)
0a753a76 240{
68dc0745 241 int r;
0a753a76 242
326b05e3 243 SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen));
68dc0745 244 return r;
0a753a76 245}
246
2d7a9237 247int
68dc0745 248win32_ioctlsocket(SOCKET s, long cmd, u_long *argp)
0a753a76 249{
68dc0745 250 int r;
0a753a76 251
326b05e3 252 SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp));
68dc0745 253 return r;
0a753a76 254}
255
68dc0745 256int
257win32_listen(SOCKET s, int backlog)
0a753a76 258{
68dc0745 259 int r;
0a753a76 260
326b05e3 261 SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog));
68dc0745 262 return r;
0a753a76 263}
264
68dc0745 265int
266win32_recv(SOCKET s, char *buf, int len, int flags)
0a753a76 267{
68dc0745 268 int r;
0a753a76 269
326b05e3 270 SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags));
68dc0745 271 return r;
0a753a76 272}
273
68dc0745 274int
275win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
0a753a76 276{
68dc0745 277 int r;
e4449fe1 278 int frombufsize = *fromlen;
0a753a76 279
326b05e3 280 SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen));
e4449fe1
GS
281 /* Winsock's recvfrom() only returns a valid 'from' when the socket
282 * is connectionless. Perl expects a valid 'from' for all types
283 * of sockets, so go the extra mile.
284 */
285 if (r != SOCKET_ERROR && frombufsize == *fromlen)
286 (void)win32_getpeername(s, from, fromlen);
68dc0745 287 return r;
0a753a76 288}
289
68dc0745 290/* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */
291int
55d25626 292win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout)
0a753a76 293{
55d25626
GS
294 int r;
295#ifdef USE_SOCKETS_AS_HANDLES
296 Perl_fd_set dummy;
68dc0745 297 int i, fd, bit, offset;
55d25626 298 FD_SET nrd, nwr, nex, *prd, *pwr, *pex;
0a753a76 299
7e3be867
GS
300 /* winsock seems incapable of dealing with all three null fd_sets,
301 * so do the (millisecond) sleep as a special case
302 */
303 if (!(rd || wr || ex)) {
87c2f9c4
BZ
304 if (timeout)
305 Sleep(timeout->tv_sec * 1000 +
306 timeout->tv_usec / 1000); /* do the best we can */
307 else
308 Sleep(UINT_MAX);
7e3be867
GS
309 return 0;
310 }
f2bb5751 311 StartSockets();
55d25626 312 PERL_FD_ZERO(&dummy);
68dc0745 313 if (!rd)
314 rd = &dummy, prd = NULL;
315 else
316 prd = &nrd;
317 if (!wr)
318 wr = &dummy, pwr = NULL;
319 else
320 pwr = &nwr;
321 if (!ex)
322 ex = &dummy, pex = NULL;
323 else
324 pex = &nex;
0a753a76 325
68dc0745 326 FD_ZERO(&nrd);
327 FD_ZERO(&nwr);
328 FD_ZERO(&nex);
329 for (i = 0; i < nfds; i++) {
330 fd = TO_SOCKET(i);
55d25626 331 if (PERL_FD_ISSET(i,rd))
68dc0745 332 FD_SET(fd, &nrd);
55d25626 333 if (PERL_FD_ISSET(i,wr))
68dc0745 334 FD_SET(fd, &nwr);
55d25626 335 if (PERL_FD_ISSET(i,ex))
68dc0745 336 FD_SET(fd, &nex);
337 }
338
326b05e3 339 SOCKET_TEST_ERROR(r = select(nfds, prd, pwr, pex, timeout));
0a753a76 340
68dc0745 341 for (i = 0; i < nfds; i++) {
342 fd = TO_SOCKET(i);
55d25626
GS
343 if (PERL_FD_ISSET(i,rd) && !FD_ISSET(fd, &nrd))
344 PERL_FD_CLR(i,rd);
345 if (PERL_FD_ISSET(i,wr) && !FD_ISSET(fd, &nwr))
346 PERL_FD_CLR(i,wr);
347 if (PERL_FD_ISSET(i,ex) && !FD_ISSET(fd, &nex))
348 PERL_FD_CLR(i,ex);
68dc0745 349 }
55d25626
GS
350#else
351 SOCKET_TEST_ERROR(r = select(nfds, rd, wr, ex, timeout));
352#endif
68dc0745 353 return r;
0a753a76 354}
355
68dc0745 356int
357win32_send(SOCKET s, const char *buf, int len, int flags)
0a753a76 358{
68dc0745 359 int r;
0a753a76 360
326b05e3 361 SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags));
68dc0745 362 return r;
0a753a76 363}
364
68dc0745 365int
366win32_sendto(SOCKET s, const char *buf, int len, int flags,
367 const struct sockaddr *to, int tolen)
0a753a76 368{
68dc0745 369 int r;
0a753a76 370
326b05e3 371 SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen));
68dc0745 372 return r;
0a753a76 373}
374
68dc0745 375int
376win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
0a753a76 377{
68dc0745 378 int r;
0a753a76 379
326b05e3 380 SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen));
68dc0745 381 return r;
0a753a76 382}
383
68dc0745 384int
385win32_shutdown(SOCKET s, int how)
0a753a76 386{
68dc0745 387 int r;
0a753a76 388
326b05e3 389 SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how));
68dc0745 390 return r;
0a753a76 391}
392
3a25acb4
GS
393int
394win32_closesocket(SOCKET s)
395{
396 int r;
397
398 SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s)));
399 return r;
400}
401
68dc0745 402SOCKET
403win32_socket(int af, int type, int protocol)
0a753a76 404{
68dc0745 405 SOCKET s;
0a753a76 406
407#ifndef USE_SOCKETS_AS_HANDLES
326b05e3 408 SOCKET_TEST(s = socket(af, type, protocol), INVALID_SOCKET);
0a753a76 409#else
3a25acb4 410 StartSockets();
326b05e3
GS
411 if((s = socket(af, type, protocol)) == INVALID_SOCKET)
412 errno = WSAGetLastError();
68dc0745 413 else
414 s = OPEN_SOCKET(s);
415#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 416
68dc0745 417 return s;
0a753a76 418}
419
fb73857a 420#undef fclose
421int
422my_fclose (FILE *pf)
423{
326b05e3
GS
424 int osf, retval;
425 if (!wsock_started) /* No WinSock? */
426 return(fclose(pf)); /* Then not a socket. */
427 osf = TO_SOCKET(fileno(pf));/* Get it now before it's gone! */
428 retval = fclose(pf); /* Must fclose() before closesocket() */
429 if (osf != -1
430 && closesocket(osf) == SOCKET_ERROR
431 && WSAGetLastError() != WSAENOTSOCK)
432 {
433 return EOF;
434 }
435 return retval;
fb73857a 436}
437
68dc0745 438struct hostent *
439win32_gethostbyaddr(const char *addr, int len, int type)
0a753a76 440{
68dc0745 441 struct hostent *r;
0a753a76 442
326b05e3 443 SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL);
68dc0745 444 return r;
0a753a76 445}
446
68dc0745 447struct hostent *
448win32_gethostbyname(const char *name)
0a753a76 449{
68dc0745 450 struct hostent *r;
0a753a76 451
326b05e3 452 SOCKET_TEST(r = gethostbyname(name), NULL);
68dc0745 453 return r;
0a753a76 454}
455
68dc0745 456int
457win32_gethostname(char *name, int len)
0a753a76 458{
68dc0745 459 int r;
0a753a76 460
326b05e3 461 SOCKET_TEST_ERROR(r = gethostname(name, len));
68dc0745 462 return r;
0a753a76 463}
464
68dc0745 465struct protoent *
466win32_getprotobyname(const char *name)
0a753a76 467{
68dc0745 468 struct protoent *r;
0a753a76 469
326b05e3 470 SOCKET_TEST(r = getprotobyname(name), NULL);
68dc0745 471 return r;
0a753a76 472}
473
68dc0745 474struct protoent *
475win32_getprotobynumber(int num)
0a753a76 476{
68dc0745 477 struct protoent *r;
0a753a76 478
326b05e3 479 SOCKET_TEST(r = getprotobynumber(num), NULL);
68dc0745 480 return r;
0a753a76 481}
482
68dc0745 483struct servent *
484win32_getservbyname(const char *name, const char *proto)
0a753a76 485{
c5be433b 486 dTHXo;
68dc0745 487 struct servent *r;
c53bd28a 488
326b05e3 489 SOCKET_TEST(r = getservbyname(name, proto), NULL);
68dc0745 490 if (r) {
3352bfcb 491 r = win32_savecopyservent(&w32_servent, r, proto);
68dc0745 492 }
493 return r;
0a753a76 494}
495
68dc0745 496struct servent *
497win32_getservbyport(int port, const char *proto)
0a753a76 498{
c5be433b 499 dTHXo;
68dc0745 500 struct servent *r;
0a753a76 501
326b05e3 502 SOCKET_TEST(r = getservbyport(port, proto), NULL);
68dc0745 503 if (r) {
3352bfcb 504 r = win32_savecopyservent(&w32_servent, r, proto);
68dc0745 505 }
506 return r;
0a753a76 507}
508
f998180f
GS
509int
510win32_ioctl(int i, unsigned int u, char *data)
511{
c5be433b 512 dTHXo;
f998180f
GS
513 u_long argp = (u_long)data;
514 int retval;
515
516 if (!wsock_started) {
4f63d024 517 Perl_croak_nocontext("ioctl implemented only on sockets");
f998180f
GS
518 /* NOTREACHED */
519 }
520
521 retval = ioctlsocket(TO_SOCKET(i), (long)u, &argp);
522 if (retval == SOCKET_ERROR) {
523 if (WSAGetLastError() == WSAENOTSOCK) {
4f63d024 524 Perl_croak_nocontext("ioctl implemented only on sockets");
f998180f
GS
525 /* NOTREACHED */
526 }
527 errno = WSAGetLastError();
528 }
529 return retval;
530}
531
68dc0745 532char FAR *
533win32_inet_ntoa(struct in_addr in)
0a753a76 534{
326b05e3
GS
535 StartSockets();
536 return inet_ntoa(in);
0a753a76 537}
538
68dc0745 539unsigned long
540win32_inet_addr(const char FAR *cp)
0a753a76 541{
326b05e3
GS
542 StartSockets();
543 return inet_addr(cp);
0a753a76 544}
68dc0745 545
546/*
547 * Networking stubs
548 */
0a753a76 549
68dc0745 550void
551win32_endhostent()
0a753a76 552{
c5be433b 553 dTHXo;
4f63d024 554 Perl_croak_nocontext("endhostent not implemented!\n");
0a753a76 555}
556
68dc0745 557void
558win32_endnetent()
0a753a76 559{
c5be433b 560 dTHXo;
4f63d024 561 Perl_croak_nocontext("endnetent not implemented!\n");
0a753a76 562}
563
68dc0745 564void
565win32_endprotoent()
0a753a76 566{
c5be433b 567 dTHXo;
4f63d024 568 Perl_croak_nocontext("endprotoent not implemented!\n");
0a753a76 569}
570
68dc0745 571void
572win32_endservent()
0a753a76 573{
c5be433b 574 dTHXo;
4f63d024 575 Perl_croak_nocontext("endservent not implemented!\n");
0a753a76 576}
577
578
68dc0745 579struct netent *
580win32_getnetent(void)
0a753a76 581{
c5be433b 582 dTHXo;
4f63d024 583 Perl_croak_nocontext("getnetent not implemented!\n");
68dc0745 584 return (struct netent *) NULL;
0a753a76 585}
586
68dc0745 587struct netent *
588win32_getnetbyname(char *name)
0a753a76 589{
c5be433b 590 dTHXo;
4f63d024 591 Perl_croak_nocontext("getnetbyname not implemented!\n");
68dc0745 592 return (struct netent *)NULL;
0a753a76 593}
594
68dc0745 595struct netent *
596win32_getnetbyaddr(long net, int type)
0a753a76 597{
c5be433b 598 dTHXo;
4f63d024 599 Perl_croak_nocontext("getnetbyaddr not implemented!\n");
68dc0745 600 return (struct netent *)NULL;
0a753a76 601}
602
68dc0745 603struct protoent *
604win32_getprotoent(void)
0a753a76 605{
c5be433b 606 dTHXo;
4f63d024 607 Perl_croak_nocontext("getprotoent not implemented!\n");
68dc0745 608 return (struct protoent *) NULL;
0a753a76 609}
610
68dc0745 611struct servent *
612win32_getservent(void)
0a753a76 613{
c5be433b 614 dTHXo;
4f63d024 615 Perl_croak_nocontext("getservent not implemented!\n");
68dc0745 616 return (struct servent *) NULL;
0a753a76 617}
618
68dc0745 619void
620win32_sethostent(int stayopen)
0a753a76 621{
c5be433b 622 dTHXo;
4f63d024 623 Perl_croak_nocontext("sethostent not implemented!\n");
0a753a76 624}
625
626
68dc0745 627void
628win32_setnetent(int stayopen)
0a753a76 629{
c5be433b 630 dTHXo;
4f63d024 631 Perl_croak_nocontext("setnetent not implemented!\n");
0a753a76 632}
633
634
68dc0745 635void
636win32_setprotoent(int stayopen)
0a753a76 637{
c5be433b 638 dTHXo;
4f63d024 639 Perl_croak_nocontext("setprotoent not implemented!\n");
0a753a76 640}
641
642
68dc0745 643void
644win32_setservent(int stayopen)
0a753a76 645{
c5be433b 646 dTHXo;
4f63d024 647 Perl_croak_nocontext("setservent not implemented!\n");
0a753a76 648}
649
137443ea 650static struct servent*
651win32_savecopyservent(struct servent*d, struct servent*s, const char *proto)
652{
653 d->s_name = s->s_name;
654 d->s_aliases = s->s_aliases;
655 d->s_port = s->s_port;
0af56dfe 656#ifndef __BORLANDC__ /* Buggy on Win95 and WinNT-with-Borland-WSOCK */
137443ea 657 if (!IsWin95() && s->s_proto && strlen(s->s_proto))
658 d->s_proto = s->s_proto;
0af56dfe
GS
659 else
660#endif
c69f6586 661 if (proto && strlen(proto))
137443ea 662 d->s_proto = (char *)proto;
663 else
664 d->s_proto = "tcp";
665
666 return d;
667}
668
0a753a76 669