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