[win32] various hacks to get mingw32 to build. Sync Makefile with makefile.mk.
[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
68dc0745 226int
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
68dc0745 469char FAR *
470win32_inet_ntoa(struct in_addr in)
0a753a76 471{
326b05e3 472 StartSockets();
473 return inet_ntoa(in);
0a753a76 474}
475
68dc0745 476unsigned long
477win32_inet_addr(const char FAR *cp)
0a753a76 478{
326b05e3 479 StartSockets();
480 return inet_addr(cp);
0a753a76 481}
68dc0745 482
483/*
484 * Networking stubs
485 */
0a753a76 486
68dc0745 487void
488win32_endhostent()
0a753a76 489{
326b05e3 490 croak("endhostent not implemented!\n");
0a753a76 491}
492
68dc0745 493void
494win32_endnetent()
0a753a76 495{
326b05e3 496 croak("endnetent not implemented!\n");
0a753a76 497}
498
68dc0745 499void
500win32_endprotoent()
0a753a76 501{
326b05e3 502 croak("endprotoent not implemented!\n");
0a753a76 503}
504
68dc0745 505void
506win32_endservent()
0a753a76 507{
326b05e3 508 croak("endservent not implemented!\n");
0a753a76 509}
510
511
68dc0745 512struct netent *
513win32_getnetent(void)
0a753a76 514{
326b05e3 515 croak("getnetent not implemented!\n");
68dc0745 516 return (struct netent *) NULL;
0a753a76 517}
518
68dc0745 519struct netent *
520win32_getnetbyname(char *name)
0a753a76 521{
326b05e3 522 croak("getnetbyname not implemented!\n");
68dc0745 523 return (struct netent *)NULL;
0a753a76 524}
525
68dc0745 526struct netent *
527win32_getnetbyaddr(long net, int type)
0a753a76 528{
326b05e3 529 croak("getnetbyaddr not implemented!\n");
68dc0745 530 return (struct netent *)NULL;
0a753a76 531}
532
68dc0745 533struct protoent *
534win32_getprotoent(void)
0a753a76 535{
326b05e3 536 croak("getprotoent not implemented!\n");
68dc0745 537 return (struct protoent *) NULL;
0a753a76 538}
539
68dc0745 540struct servent *
541win32_getservent(void)
0a753a76 542{
326b05e3 543 croak("getservent not implemented!\n");
68dc0745 544 return (struct servent *) NULL;
0a753a76 545}
546
68dc0745 547void
548win32_sethostent(int stayopen)
0a753a76 549{
326b05e3 550 croak("sethostent not implemented!\n");
0a753a76 551}
552
553
68dc0745 554void
555win32_setnetent(int stayopen)
0a753a76 556{
326b05e3 557 croak("setnetent not implemented!\n");
0a753a76 558}
559
560
68dc0745 561void
562win32_setprotoent(int stayopen)
0a753a76 563{
326b05e3 564 croak("setprotoent not implemented!\n");
0a753a76 565}
566
567
68dc0745 568void
569win32_setservent(int stayopen)
0a753a76 570{
326b05e3 571 croak("setservent not implemented!\n");
0a753a76 572}
573
137443ea 574static struct servent*
575win32_savecopyservent(struct servent*d, struct servent*s, const char *proto)
576{
577 d->s_name = s->s_name;
578 d->s_aliases = s->s_aliases;
579 d->s_port = s->s_port;
0af56dfe 580#ifndef __BORLANDC__ /* Buggy on Win95 and WinNT-with-Borland-WSOCK */
137443ea 581 if (!IsWin95() && s->s_proto && strlen(s->s_proto))
582 d->s_proto = s->s_proto;
0af56dfe 583 else
584#endif
585 if (proto && strlen(proto))
137443ea 586 d->s_proto = (char *)proto;
587 else
588 d->s_proto = "tcp";
589
590 return d;
591}
592
0a753a76 593