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