Threadsafe patches
[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"
c69f6586 20
21#if defined(PERL_OBJECT)
22#define NO_XSLOCKS
c69f6586 23#include "XSUB.h"
24#endif
25
58a50f62 26#include "Win32iop.h"
0a753a76 27#include <sys/socket.h>
28#include <fcntl.h>
29#include <sys/stat.h>
77c631e4 30#ifndef __MINGW32__
0a753a76 31#include <assert.h>
77c631e4 32#endif
390b85e7 33#include <io.h>
0a753a76 34
68dc0745 35/* thanks to Beverly Brown (beverly@datacube.com) */
326b05e3 36#ifdef USE_SOCKETS_AS_HANDLES
58a50f62 37# define OPEN_SOCKET(x) win32_open_osfhandle(x,O_RDWR|O_BINARY)
326b05e3 38# define TO_SOCKET(x) _get_osfhandle(x)
0a753a76 39#else
0a753a76 40# define OPEN_SOCKET(x) (x)
41# define TO_SOCKET(x) (x)
68dc0745 42#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 43
77c631e4 44#if defined(USE_THREADS) || defined(USE_ITHREADS)
326b05e3 45#define StartSockets() \
46 STMT_START { \
47 if (!wsock_started) \
48 start_sockets(); \
401ef382 49 set_socktype(); \
326b05e3 50 } STMT_END
401ef382 51#else
52#define StartSockets() \
53 STMT_START { \
54 if (!wsock_started) { \
55 start_sockets(); \
56 set_socktype(); \
57 } \
58 } STMT_END
59#endif
326b05e3 60
326b05e3 61#define SOCKET_TEST(x, y) \
62 STMT_START { \
63 StartSockets(); \
64 if((x) == (y)) \
77c631e4 65 errno = CALL(WSAGetLastError)(); \
326b05e3 66 } STMT_END
67
68#define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
69
137443ea 70static struct servent* win32_savecopyservent(struct servent*d,
71 struct servent*s,
72 const char *proto);
0a753a76 73
326b05e3 74static int wsock_started = 0;
68dc0745 75
77c631e4 76#ifdef PERL_WIN32_SOCK_DLOAD /* we load the socket libraries when needed -- BKS 5-29-2000 */
77#define CALL(x) (*p ## x)
78typedef SOCKET (PASCAL *Paccept)(SOCKET,struct sockaddr*,int*);
79typedef int (PASCAL *Pbind)(SOCKET,const struct sockaddr*,int);
80typedef int (PASCAL *Pclosesocket)(SOCKET);
81typedef int (PASCAL *Pconnect)(SOCKET,const struct sockaddr*,int);
82typedef int (PASCAL *Pioctlsocket)(SOCKET,long,u_long *);
83typedef int (PASCAL *Pgetpeername)(SOCKET,struct sockaddr*,int*);
84typedef int (PASCAL *Pgetsockname)(SOCKET,struct sockaddr*,int*);
85typedef int (PASCAL *Pgetsockopt)(SOCKET,int,int,char*,int*);
86typedef unsigned long (PASCAL *Pinet_addr)(const char*);
87typedef char * (PASCAL *Pinet_ntoa)(struct in_addr);
88typedef int (PASCAL *Plisten)(SOCKET,int);
89typedef int (PASCAL *Precv)(SOCKET,char*,int,int);
90typedef int (PASCAL *Precvfrom)(SOCKET,char*,int,int,struct sockaddr*,int*);
91typedef int (PASCAL *Psend)(SOCKET,const char*,int,int);
92typedef int (PASCAL *Psendto)(SOCKET,const char*,int,int,const struct sockaddr*,int);
93typedef int (PASCAL *Psetsockopt)(SOCKET,int,int,const char*,int);
94typedef int (PASCAL *Pshutdown)(SOCKET,int);
95typedef SOCKET (PASCAL *Psocket)(int,int,int);
96typedef struct hostent* (PASCAL *Pgethostbyaddr)(const char*,int,int);
97typedef struct hostent* (PASCAL *Pgethostbyname)(const char*);
98typedef struct servent* (PASCAL *Pgetservbyport)(int,const char*);
99typedef struct servent* (PASCAL *Pgetservbyname)(const char*,const char*);
100typedef struct protoent* (PASCAL *Pgetprotobynumber)(int);
101typedef struct protoent* (PASCAL *Pgetprotobyname)(const char*);
102typedef int (PASCAL *PWSACleanup)(void);
103typedef int (PASCAL *PWSAStartup)(unsigned short, WSADATA*);
104typedef void (PASCAL *PWSASetLastError)(int);
105typedef int (PASCAL *PWSAGetLastError)(void);
106typedef int (PASCAL *P__WSAFDIsSet)(SOCKET,fd_set*);
107typedef int (PASCAL *Pselect)(int nfds,fd_set*,fd_set*,fd_set*,const struct timeval*);
108typedef int (PASCAL *Pgethostname)(char*,int);
109typedef u_long (PASCAL *Phtonl)(u_long), (PASCAL *Pntohl)(u_long);
110typedef u_short (PASCAL *Phtons)(u_short), (PASCAL *Pntohs)(u_short);
111static Paccept paccept;
112static Pbind pbind;
113static Pclosesocket pclosesocket;
114static Pconnect pconnect;
115static Pioctlsocket pioctlsocket;
116static Pgetpeername pgetpeername;
117static Pgetsockname pgetsockname;
118static Pgetsockopt pgetsockopt;
119static Pinet_addr pinet_addr;
120static Pinet_ntoa pinet_ntoa;
121static Plisten plisten;
122static Precv precv;
123static Precvfrom precvfrom;
124static Psend psend;
125static Psendto psendto;
126static Psetsockopt psetsockopt;
127static Pshutdown pshutdown;
128static Psocket psocket;
129static Pgethostbyaddr pgethostbyaddr;
130static Pgethostbyname pgethostbyname;
131static Pgetservbyport pgetservbyport;
132static Pgetservbyname pgetservbyname;
133static Pgetprotobynumber pgetprotobynumber;
134static Pgetprotobyname pgetprotobyname;
135static PWSAStartup pWSAStartup;
136static PWSACleanup pWSACleanup;
137static PWSASetLastError pWSASetLastError;
138static PWSAGetLastError pWSAGetLastError;
139static P__WSAFDIsSet p__WSAFDIsSet;
140static Pselect pselect;
141static Pgethostname pgethostname;
142#if BYTEORDER != 0x1234
143static Phtons phtons;
144static Pntohs pntohs;
145static Phtonl phtonl;
146static Pntohl pntohl;
147#endif
148void end_sockets(pTHXo_ void *ptr)
149{
150 CALL(WSACleanup)();
151 wsock_started = 0;
152 FreeLibrary(ptr);
153}
154#else
155#define CALL(x) x
156#endif /* PERL_WIN32_SOCK_DLOAD */
68dc0745 157void
326b05e3 158start_sockets(void)
68dc0745 159{
c5be433b 160 dTHXo;
68dc0745 161 unsigned short version;
162 WSADATA retdata;
163 int ret;
77c631e4 164#ifdef PERL_WIN32_SOCK_DLOAD
165 HANDLE hDll = LoadLibraryA("wsock32.dll");
68dc0745 166
68dc0745 167 /*
168 * initalize the winsock interface and insure that it is
169 * cleaned up at exit.
77c631e4 170 * Also, only load the DLL when needed -- BKS, 4-2-2000
68dc0745 171 */
77c631e4 172 if (!(hDll &&
173 (paccept = (Paccept)GetProcAddress(hDll, "accept")) &&
174 (pbind = (Pbind)GetProcAddress(hDll, "bind")) &&
175 (pclosesocket = (Pclosesocket)GetProcAddress(hDll, "closesocket")) &&
176 (pconnect = (Pconnect)GetProcAddress(hDll, "connect")) &&
177 (pioctlsocket = (Pioctlsocket)GetProcAddress(hDll, "ioctlsocket")) &&
178 (pgetpeername = (Pgetpeername)GetProcAddress(hDll, "getpeername")) &&
179 (pgetsockname = (Pgetsockname)GetProcAddress(hDll, "getsockname")) &&
180 (pgetsockopt = (Pgetsockopt)GetProcAddress(hDll, "getsockopt")) &&
181 (pinet_addr = (Pinet_addr)GetProcAddress(hDll, "inet_addr")) &&
182 (pinet_ntoa = (Pinet_ntoa)GetProcAddress(hDll, "inet_ntoa")) &&
183 (plisten = (Plisten)GetProcAddress(hDll, "listen")) &&
184 (precv = (Precv)GetProcAddress(hDll, "recv")) &&
185 (precvfrom = (Precvfrom)GetProcAddress(hDll, "recvfrom")) &&
186 (psend = (Psend)GetProcAddress(hDll, "send")) &&
187 (psendto = (Psendto)GetProcAddress(hDll, "sendto")) &&
188 (psetsockopt = (Psetsockopt)GetProcAddress(hDll, "setsockopt")) &&
189 (pshutdown = (Pshutdown)GetProcAddress(hDll, "shutdown")) &&
190 (psocket = (Psocket)GetProcAddress(hDll, "socket")) &&
191 (pgethostbyaddr = (Pgethostbyaddr)GetProcAddress(hDll, "gethostbyaddr")) &&
192 (pgethostbyname = (Pgethostbyname)GetProcAddress(hDll, "gethostbyname")) &&
193 (pgetservbyport = (Pgetservbyport)GetProcAddress(hDll, "getservbyport")) &&
194 (pgetservbyname = (Pgetservbyname)GetProcAddress(hDll, "getservbyname")) &&
195 (pgetprotobynumber = (Pgetprotobynumber)GetProcAddress(hDll, "getprotobynumber")) &&
196 (pgetprotobyname = (Pgetprotobyname)GetProcAddress(hDll, "getprotobyname")) &&
197 (pWSAStartup = (PWSAStartup)GetProcAddress(hDll, "WSAStartup")) &&
198 (pWSACleanup = (PWSACleanup)GetProcAddress(hDll, "WSACleanup")) &&
199 (pWSASetLastError = (PWSASetLastError)GetProcAddress(hDll, "WSASetLastError")) &&
200 (pWSAGetLastError = (PWSAGetLastError)GetProcAddress(hDll, "WSAGetLastError")) &&
201 (p__WSAFDIsSet = (P__WSAFDIsSet)GetProcAddress(hDll, "__WSAFDIsSet")) &&
202 (pselect = (Pselect)GetProcAddress(hDll, "select")) &&
203 (pgethostname = (Pgethostname)GetProcAddress(hDll, "gethostname")) &&
204#if BYTEORDER != 0x1234
205 (phtonl = (Phtonl)GetProcAddress(hDll, "htonl")) &&
206 (pntohl = (Pntohl)GetProcAddress(hDll, "ntohl")) &&
207 (phtons = (Pntohs)GetProcAddress(hDll, "htons")) &&
208 (pntohs = (Pntohs)GetProcAddress(hDll, "ntohs")
209#else
210 1
211#endif
212 )) {
213 Perl_croak(aTHX_ "Unable to load winsock library!\n");
214 }
215#endif /* PERL_WIN32_SOCK_DLOAD */
68dc0745 216 version = 0x101;
77c631e4 217 if(ret = CALL(WSAStartup)(version, &retdata))
218 Perl_croak(aTHX_ "Unable to initialize winsock library!\n");
68dc0745 219 if(retdata.wVersion != version)
77c631e4 220 Perl_croak(aTHX_ "Could not find version 1.1 of winsock dll\n");
68dc0745 221
77c631e4 222#ifdef PERL_WIN32_SOCK_DLOAD
223 call_atexit(end_sockets, hDll);
224#endif
401ef382 225 wsock_started = 1;
226}
0a753a76 227
401ef382 228void
229set_socktype(void)
230{
0a753a76 231#ifdef USE_SOCKETS_AS_HANDLES
401ef382 232#ifdef USE_THREADS
4f63d024 233 dTHX;
3352bfcb 234 if (!w32_init_socktype) {
401ef382 235#endif
3352bfcb 236 int iSockOpt = SO_SYNCHRONOUS_NONALERT;
237 /*
238 * Enable the use of sockets as filehandles
239 */
77c631e4 240 CALL(setsockopt)(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
3352bfcb 241 (char *)&iSockOpt, sizeof(iSockOpt));
401ef382 242#ifdef USE_THREADS
3352bfcb 243 w32_init_socktype = 1;
401ef382 244 }
245#endif
68dc0745 246#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 247}
248
249
250#ifndef USE_SOCKETS_AS_HANDLES
f3986ebb 251#undef fdopen
68dc0745 252FILE *
f3986ebb 253my_fdopen(int fd, char *mode)
0a753a76 254{
68dc0745 255 FILE *fp;
256 char sockbuf[256];
257 int optlen = sizeof(sockbuf);
258 int retval;
0a753a76 259
326b05e3 260 if (!wsock_started)
fb73857a 261 return(fdopen(fd, mode));
0a753a76 262
77c631e4 263 retval = CALL(getsockopt)((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
264 if(retval == SOCKET_ERROR && CALL(WSAGetLastError)() == WSAENOTSOCK) {
fb73857a 265 return(fdopen(fd, mode));
68dc0745 266 }
0a753a76 267
68dc0745 268 /*
269 * If we get here, then fd is actually a socket.
270 */
fc36a67e 271 Newz(1310, fp, 1, FILE);
68dc0745 272 if(fp == NULL) {
273 errno = ENOMEM;
274 return NULL;
275 }
0a753a76 276
68dc0745 277 fp->_file = fd;
278 if(*mode == 'r')
279 fp->_flag = _IOREAD;
280 else
281 fp->_flag = _IOWRT;
282
283 return fp;
0a753a76 284}
68dc0745 285#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 286
77c631e4 287/* ntoh* and hton* are implemented here so that ByteLoader doesn't need to load WinSock;
288 these functions are simply copied from util.c */
0a753a76 289
68dc0745 290u_long
77c631e4 291win32_htonl(u_long l)
292{
293#if BYTEORDER == 0x1234
294 union { u_long r; char c[4]; } u;
295 u.c[0] = (l >> 24) & 255;
296 u.c[1] = (l >> 16) & 255;
297 u.c[2] = (l >> 8) & 255;
298 u.c[3] = l & 255;
299 return u.r;
300#else
326b05e3 301 StartSockets();
77c631e4 302 return CALL(htonl)(l);
303#endif
0a753a76 304}
305
68dc0745 306u_short
77c631e4 307win32_htons(u_short s)
0a753a76 308{
77c631e4 309#if BYTEORDER == 0x1234
310 return (((s >> 8) & 255) | ((s & 255) << 8));
311#else
326b05e3 312 StartSockets();
77c631e4 313 return CALL(htons)(s);
314#endif
0a753a76 315}
316
68dc0745 317u_long
77c631e4 318win32_ntohl(u_long l)
319{
320#if BYTEORDER == 0x1234
321 union { u_long r; char c[4]; } u;
322 u.c[0] = (l >> 24) & 255;
323 u.c[1] = (l >> 16) & 255;
324 u.c[2] = (l >> 8) & 255;
325 u.c[3] = l & 255;
326 return u.r;
327#else
326b05e3 328 StartSockets();
77c631e4 329 return CALL(ntohl)(l);
330#endif
0a753a76 331}
332
68dc0745 333u_short
77c631e4 334win32_ntohs(u_short s)
0a753a76 335{
77c631e4 336#if BYTEORDER == 0x1234
337 return (((s >> 8) & 255) | ((s & 255) << 8));
338#else
326b05e3 339 StartSockets();
77c631e4 340 return CALL(ntohs)(s);
341#endif
0a753a76 342}
343
344
0a753a76 345
68dc0745 346SOCKET
347win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 348{
68dc0745 349 SOCKET r;
0a753a76 350
77c631e4 351 SOCKET_TEST((r = CALL(accept)(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
68dc0745 352 return OPEN_SOCKET(r);
0a753a76 353}
354
68dc0745 355int
356win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen)
0a753a76 357{
68dc0745 358 int r;
0a753a76 359
77c631e4 360 SOCKET_TEST_ERROR(r = CALL(bind)(TO_SOCKET(s), addr, addrlen));
68dc0745 361 return r;
0a753a76 362}
363
68dc0745 364int
365win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
0a753a76 366{
68dc0745 367 int r;
0a753a76 368
77c631e4 369 SOCKET_TEST_ERROR(r = CALL(connect)(TO_SOCKET(s), addr, addrlen));
68dc0745 370 return r;
0a753a76 371}
372
373
68dc0745 374int
375win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 376{
68dc0745 377 int r;
0a753a76 378
77c631e4 379 SOCKET_TEST_ERROR(r = CALL(getpeername)(TO_SOCKET(s), addr, addrlen));
68dc0745 380 return r;
0a753a76 381}
382
68dc0745 383int
384win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 385{
68dc0745 386 int r;
0a753a76 387
77c631e4 388 SOCKET_TEST_ERROR(r = CALL(getsockname)(TO_SOCKET(s), addr, addrlen));
68dc0745 389 return r;
0a753a76 390}
391
68dc0745 392int
393win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen)
0a753a76 394{
68dc0745 395 int r;
0a753a76 396
77c631e4 397 SOCKET_TEST_ERROR(r = CALL(getsockopt)(TO_SOCKET(s), level, optname, optval, optlen));
68dc0745 398 return r;
0a753a76 399}
400
2d7a9237 401int
68dc0745 402win32_ioctlsocket(SOCKET s, long cmd, u_long *argp)
0a753a76 403{
68dc0745 404 int r;
0a753a76 405
77c631e4 406 SOCKET_TEST_ERROR(r = CALL(ioctlsocket)(TO_SOCKET(s), cmd, argp));
68dc0745 407 return r;
0a753a76 408}
409
68dc0745 410int
411win32_listen(SOCKET s, int backlog)
0a753a76 412{
68dc0745 413 int r;
0a753a76 414
77c631e4 415 SOCKET_TEST_ERROR(r = CALL(listen)(TO_SOCKET(s), backlog));
68dc0745 416 return r;
0a753a76 417}
418
68dc0745 419int
420win32_recv(SOCKET s, char *buf, int len, int flags)
0a753a76 421{
68dc0745 422 int r;
0a753a76 423
77c631e4 424 SOCKET_TEST_ERROR(r = CALL(recv)(TO_SOCKET(s), buf, len, flags));
68dc0745 425 return r;
0a753a76 426}
427
68dc0745 428int
429win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
0a753a76 430{
68dc0745 431 int r;
e4449fe1 432 int frombufsize = *fromlen;
0a753a76 433
77c631e4 434 SOCKET_TEST_ERROR(r = CALL(recvfrom)(TO_SOCKET(s), buf, len, flags, from, fromlen));
e4449fe1 435 /* Winsock's recvfrom() only returns a valid 'from' when the socket
436 * is connectionless. Perl expects a valid 'from' for all types
437 * of sockets, so go the extra mile.
438 */
439 if (r != SOCKET_ERROR && frombufsize == *fromlen)
440 (void)win32_getpeername(s, from, fromlen);
68dc0745 441 return r;
0a753a76 442}
443
68dc0745 444/* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */
445int
55d25626 446win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout)
0a753a76 447{
55d25626 448 int r;
449#ifdef USE_SOCKETS_AS_HANDLES
450 Perl_fd_set dummy;
68dc0745 451 int i, fd, bit, offset;
55d25626 452 FD_SET nrd, nwr, nex, *prd, *pwr, *pex;
0a753a76 453
7e3be867 454 /* winsock seems incapable of dealing with all three null fd_sets,
455 * so do the (millisecond) sleep as a special case
456 */
457 if (!(rd || wr || ex)) {
87c2f9c4 458 if (timeout)
459 Sleep(timeout->tv_sec * 1000 +
460 timeout->tv_usec / 1000); /* do the best we can */
461 else
462 Sleep(UINT_MAX);
7e3be867 463 return 0;
464 }
f2bb5751 465 StartSockets();
55d25626 466 PERL_FD_ZERO(&dummy);
68dc0745 467 if (!rd)
468 rd = &dummy, prd = NULL;
469 else
470 prd = &nrd;
471 if (!wr)
472 wr = &dummy, pwr = NULL;
473 else
474 pwr = &nwr;
475 if (!ex)
476 ex = &dummy, pex = NULL;
477 else
478 pex = &nex;
0a753a76 479
68dc0745 480 FD_ZERO(&nrd);
481 FD_ZERO(&nwr);
482 FD_ZERO(&nex);
483 for (i = 0; i < nfds; i++) {
484 fd = TO_SOCKET(i);
55d25626 485 if (PERL_FD_ISSET(i,rd))
68dc0745 486 FD_SET(fd, &nrd);
55d25626 487 if (PERL_FD_ISSET(i,wr))
68dc0745 488 FD_SET(fd, &nwr);
55d25626 489 if (PERL_FD_ISSET(i,ex))
68dc0745 490 FD_SET(fd, &nex);
491 }
492
77c631e4 493 SOCKET_TEST_ERROR(r = CALL(select)(nfds, prd, pwr, pex, timeout));
0a753a76 494
68dc0745 495 for (i = 0; i < nfds; i++) {
496 fd = TO_SOCKET(i);
77c631e4 497 if (PERL_FD_ISSET(i,rd) && !CALL(__WSAFDIsSet)(fd, &nrd))
55d25626 498 PERL_FD_CLR(i,rd);
77c631e4 499 if (PERL_FD_ISSET(i,wr) && !CALL(__WSAFDIsSet)(fd, &nwr))
55d25626 500 PERL_FD_CLR(i,wr);
77c631e4 501 if (PERL_FD_ISSET(i,ex) && !CALL(__WSAFDIsSet)(fd, &nex))
55d25626 502 PERL_FD_CLR(i,ex);
68dc0745 503 }
55d25626 504#else
77c631e4 505 SOCKET_TEST_ERROR(r = CALL(select)(nfds, rd, wr, ex, timeout));
55d25626 506#endif
68dc0745 507 return r;
0a753a76 508}
509
68dc0745 510int
511win32_send(SOCKET s, const char *buf, int len, int flags)
0a753a76 512{
68dc0745 513 int r;
0a753a76 514
77c631e4 515 SOCKET_TEST_ERROR(r = CALL(send)(TO_SOCKET(s), buf, len, flags));
68dc0745 516 return r;
0a753a76 517}
518
68dc0745 519int
520win32_sendto(SOCKET s, const char *buf, int len, int flags,
521 const struct sockaddr *to, int tolen)
0a753a76 522{
68dc0745 523 int r;
0a753a76 524
77c631e4 525 SOCKET_TEST_ERROR(r = CALL(sendto)(TO_SOCKET(s), buf, len, flags, to, tolen));
68dc0745 526 return r;
0a753a76 527}
528
68dc0745 529int
530win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
0a753a76 531{
68dc0745 532 int r;
0a753a76 533
77c631e4 534 SOCKET_TEST_ERROR(r = CALL(setsockopt)(TO_SOCKET(s), level, optname, optval, optlen));
68dc0745 535 return r;
0a753a76 536}
537
68dc0745 538int
539win32_shutdown(SOCKET s, int how)
0a753a76 540{
68dc0745 541 int r;
0a753a76 542
77c631e4 543 SOCKET_TEST_ERROR(r = CALL(shutdown)(TO_SOCKET(s), how));
68dc0745 544 return r;
0a753a76 545}
546
3a25acb4 547int
548win32_closesocket(SOCKET s)
549{
550 int r;
551
77c631e4 552 SOCKET_TEST_ERROR(r = CALL(closesocket)(TO_SOCKET(s)));
3a25acb4 553 return r;
554}
555
68dc0745 556SOCKET
557win32_socket(int af, int type, int protocol)
0a753a76 558{
68dc0745 559 SOCKET s;
0a753a76 560
561#ifndef USE_SOCKETS_AS_HANDLES
77c631e4 562 SOCKET_TEST(s = CALL(socket)(af, type, protocol), INVALID_SOCKET);
0a753a76 563#else
3a25acb4 564 StartSockets();
77c631e4 565 if((s = CALL(socket)(af, type, protocol)) == INVALID_SOCKET)
566 errno = CALL(WSAGetLastError)();
68dc0745 567 else
568 s = OPEN_SOCKET(s);
569#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 570
68dc0745 571 return s;
0a753a76 572}
573
fb73857a 574#undef fclose
575int
576my_fclose (FILE *pf)
577{
326b05e3 578 int osf, retval;
579 if (!wsock_started) /* No WinSock? */
580 return(fclose(pf)); /* Then not a socket. */
581 osf = TO_SOCKET(fileno(pf));/* Get it now before it's gone! */
582 retval = fclose(pf); /* Must fclose() before closesocket() */
583 if (osf != -1
77c631e4 584 && CALL(closesocket)(osf) == SOCKET_ERROR
585 && CALL(WSAGetLastError)() != WSAENOTSOCK)
326b05e3 586 {
587 return EOF;
588 }
589 return retval;
fb73857a 590}
591
68dc0745 592struct hostent *
593win32_gethostbyaddr(const char *addr, int len, int type)
0a753a76 594{
68dc0745 595 struct hostent *r;
0a753a76 596
77c631e4 597 SOCKET_TEST(r = CALL(gethostbyaddr)(addr, len, type), NULL);
68dc0745 598 return r;
0a753a76 599}
600
68dc0745 601struct hostent *
602win32_gethostbyname(const char *name)
0a753a76 603{
68dc0745 604 struct hostent *r;
0a753a76 605
77c631e4 606 SOCKET_TEST(r = CALL(gethostbyname)(name), NULL);
68dc0745 607 return r;
0a753a76 608}
609
68dc0745 610int
611win32_gethostname(char *name, int len)
0a753a76 612{
68dc0745 613 int r;
0a753a76 614
77c631e4 615 SOCKET_TEST_ERROR(r = CALL(gethostname)(name, len));
68dc0745 616 return r;
0a753a76 617}
618
68dc0745 619struct protoent *
620win32_getprotobyname(const char *name)
0a753a76 621{
68dc0745 622 struct protoent *r;
0a753a76 623
77c631e4 624 SOCKET_TEST(r = CALL(getprotobyname)(name), NULL);
68dc0745 625 return r;
0a753a76 626}
627
68dc0745 628struct protoent *
629win32_getprotobynumber(int num)
0a753a76 630{
68dc0745 631 struct protoent *r;
0a753a76 632
77c631e4 633 SOCKET_TEST(r = CALL(getprotobynumber)(num), NULL);
68dc0745 634 return r;
0a753a76 635}
636
68dc0745 637struct servent *
638win32_getservbyname(const char *name, const char *proto)
0a753a76 639{
c5be433b 640 dTHXo;
68dc0745 641 struct servent *r;
c53bd28a 642
77c631e4 643 SOCKET_TEST(r = CALL(getservbyname)(name, proto), NULL);
68dc0745 644 if (r) {
3352bfcb 645 r = win32_savecopyservent(&w32_servent, r, proto);
68dc0745 646 }
647 return r;
0a753a76 648}
649
68dc0745 650struct servent *
651win32_getservbyport(int port, const char *proto)
0a753a76 652{
c5be433b 653 dTHXo;
68dc0745 654 struct servent *r;
0a753a76 655
77c631e4 656 SOCKET_TEST(r = CALL(getservbyport)(port, proto), NULL);
68dc0745 657 if (r) {
3352bfcb 658 r = win32_savecopyservent(&w32_servent, r, proto);
68dc0745 659 }
660 return r;
0a753a76 661}
662
f998180f 663int
664win32_ioctl(int i, unsigned int u, char *data)
665{
c5be433b 666 dTHXo;
f998180f 667 u_long argp = (u_long)data;
668 int retval;
669
670 if (!wsock_started) {
4f63d024 671 Perl_croak_nocontext("ioctl implemented only on sockets");
f998180f 672 /* NOTREACHED */
673 }
674
77c631e4 675 retval = CALL(ioctlsocket)(TO_SOCKET(i), (long)u, &argp);
f998180f 676 if (retval == SOCKET_ERROR) {
77c631e4 677 if (CALL(WSAGetLastError)() == WSAENOTSOCK) {
4f63d024 678 Perl_croak_nocontext("ioctl implemented only on sockets");
f998180f 679 /* NOTREACHED */
680 }
77c631e4 681 errno = CALL(WSAGetLastError)();
f998180f 682 }
683 return retval;
684}
685
68dc0745 686char FAR *
687win32_inet_ntoa(struct in_addr in)
0a753a76 688{
326b05e3 689 StartSockets();
77c631e4 690 return CALL(inet_ntoa)(in);
0a753a76 691}
692
68dc0745 693unsigned long
694win32_inet_addr(const char FAR *cp)
0a753a76 695{
326b05e3 696 StartSockets();
77c631e4 697 return CALL(inet_addr)(cp);
0a753a76 698}
68dc0745 699
700/*
701 * Networking stubs
702 */
0a753a76 703
68dc0745 704void
705win32_endhostent()
0a753a76 706{
c5be433b 707 dTHXo;
4f63d024 708 Perl_croak_nocontext("endhostent not implemented!\n");
0a753a76 709}
710
68dc0745 711void
712win32_endnetent()
0a753a76 713{
c5be433b 714 dTHXo;
4f63d024 715 Perl_croak_nocontext("endnetent not implemented!\n");
0a753a76 716}
717
68dc0745 718void
719win32_endprotoent()
0a753a76 720{
c5be433b 721 dTHXo;
4f63d024 722 Perl_croak_nocontext("endprotoent not implemented!\n");
0a753a76 723}
724
68dc0745 725void
726win32_endservent()
0a753a76 727{
c5be433b 728 dTHXo;
4f63d024 729 Perl_croak_nocontext("endservent not implemented!\n");
0a753a76 730}
731
732
68dc0745 733struct netent *
734win32_getnetent(void)
0a753a76 735{
c5be433b 736 dTHXo;
4f63d024 737 Perl_croak_nocontext("getnetent not implemented!\n");
68dc0745 738 return (struct netent *) NULL;
0a753a76 739}
740
68dc0745 741struct netent *
742win32_getnetbyname(char *name)
0a753a76 743{
c5be433b 744 dTHXo;
4f63d024 745 Perl_croak_nocontext("getnetbyname not implemented!\n");
68dc0745 746 return (struct netent *)NULL;
0a753a76 747}
748
68dc0745 749struct netent *
750win32_getnetbyaddr(long net, int type)
0a753a76 751{
c5be433b 752 dTHXo;
4f63d024 753 Perl_croak_nocontext("getnetbyaddr not implemented!\n");
68dc0745 754 return (struct netent *)NULL;
0a753a76 755}
756
68dc0745 757struct protoent *
758win32_getprotoent(void)
0a753a76 759{
c5be433b 760 dTHXo;
4f63d024 761 Perl_croak_nocontext("getprotoent not implemented!\n");
68dc0745 762 return (struct protoent *) NULL;
0a753a76 763}
764
68dc0745 765struct servent *
766win32_getservent(void)
0a753a76 767{
c5be433b 768 dTHXo;
4f63d024 769 Perl_croak_nocontext("getservent not implemented!\n");
68dc0745 770 return (struct servent *) NULL;
0a753a76 771}
772
68dc0745 773void
774win32_sethostent(int stayopen)
0a753a76 775{
c5be433b 776 dTHXo;
4f63d024 777 Perl_croak_nocontext("sethostent not implemented!\n");
0a753a76 778}
779
780
68dc0745 781void
782win32_setnetent(int stayopen)
0a753a76 783{
c5be433b 784 dTHXo;
4f63d024 785 Perl_croak_nocontext("setnetent not implemented!\n");
0a753a76 786}
787
788
68dc0745 789void
790win32_setprotoent(int stayopen)
0a753a76 791{
c5be433b 792 dTHXo;
4f63d024 793 Perl_croak_nocontext("setprotoent not implemented!\n");
0a753a76 794}
795
796
68dc0745 797void
798win32_setservent(int stayopen)
0a753a76 799{
c5be433b 800 dTHXo;
4f63d024 801 Perl_croak_nocontext("setservent not implemented!\n");
0a753a76 802}
803
137443ea 804static struct servent*
805win32_savecopyservent(struct servent*d, struct servent*s, const char *proto)
806{
807 d->s_name = s->s_name;
808 d->s_aliases = s->s_aliases;
809 d->s_port = s->s_port;
0af56dfe 810#ifndef __BORLANDC__ /* Buggy on Win95 and WinNT-with-Borland-WSOCK */
137443ea 811 if (!IsWin95() && s->s_proto && strlen(s->s_proto))
812 d->s_proto = s->s_proto;
0af56dfe 813 else
814#endif
c69f6586 815 if (proto && strlen(proto))
137443ea 816 d->s_proto = (char *)proto;
817 else
818 d->s_proto = "tcp";
819
820 return d;
821}
822
0a753a76 823