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