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