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