Fix C<require> in Getopt::Long to work with 5.003
[p5sagit/p5-mst-13.2.git] / win32 / win32sck.c
1 /* NTSock.C
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  */
10
11 #include <windows.h>
12 #define WIN32_LEAN_AND_MEAN
13 #include "EXTERN.h"
14 #include "perl.h"
15 #include <sys/socket.h>
16 #include <fcntl.h>
17 #include <sys/stat.h>
18 #include <assert.h>
19
20 #define CROAK croak
21
22 #ifdef USE_SOCKETS_AS_HANDLES
23 /* thanks to Beverly Brown      (beverly@datacube.com) */
24
25 #       if defined(_WIN32) && !defined(WIN95_OSFHANDLE_FIXED) && defined(_M_IX86)
26 /*#             define OPEN_SOCKET(x)   _patch_open_osfhandle(x, _O_RDWR | _O_BINARY) */
27 #               define OPEN_SOCKET(x)   _open_osfhandle(x,_O_RDWR|_O_BINARY)
28 #       else
29 #               define OPEN_SOCKET(x)   _open_osfhandle(x,_O_RDWR|_O_BINARY)
30 #       endif
31 #               define TO_SOCKET(x)     _get_osfhandle(x)
32
33 #else
34
35 #       define OPEN_SOCKET(x)   (x)
36 #       define TO_SOCKET(x)     (x)
37
38 #endif  /* USE_SOCKETS_AS_HANDLES */
39
40 /*
41  * This is a clone of fdopen so that we can handle the version of
42  * sockets that NT gets to use.
43  *
44  * The problem is that sockets are not real file handles and 
45  * cannot be fdopen'ed. This causes problems in the do_socket
46  * routine in doio.c, since it tries to create two file pointers
47  * for the socket just created. We'll fake out an fdopen and see
48  * if we can prevent perl from trying to do stdio on sockets.
49  */
50
51 #if defined(_WIN32) && !defined(WIN95_OSFHANDLE_FIXED) && defined(_M_IX86)
52
53 #       ifdef __cplusplus
54 #define EXT_C_FUNC      extern "C"
55 #       else
56 #define EXT_C_FUNC      extern
57 #       endif
58
59 EXT_C_FUNC int __cdecl _alloc_osfhnd(void);
60 EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value);
61 EXT_C_FUNC void __cdecl _lock_fhandle(int);
62 EXT_C_FUNC void __cdecl _unlock_fhandle(int);
63 EXT_C_FUNC void __cdecl _unlock(int);
64 EXT_C_FUNC struct servent* win32_savecopyservent(struct servent*d, 
65                                                  struct servent*s, const char *proto);
66
67 #if     (_MSC_VER >= 1000)
68 typedef struct  {
69     long osfhnd;    /* underlying OS file HANDLE */
70     char osfile;    /* attributes of file (e.g., open in text mode?) */
71     char pipech;    /* one char buffer for handles opened on pipes */
72 #if defined (_MT) && !defined (DLL_FOR_WIN32S)
73     int lockinitflag;
74     CRITICAL_SECTION lock;
75 #endif  /* defined (_MT) && !defined (DLL_FOR_WIN32S) */
76 }       ioinfo;
77
78 EXT_C_FUNC ioinfo * __pioinfo[];
79
80 #define IOINFO_L2E                      5
81 #define IOINFO_ARRAY_ELTS       (1 << IOINFO_L2E)
82 #define _pioinfo(i)     (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1)))
83 #define _osfile(i)      (_pioinfo(i)->osfile)
84 #else   /* (_MSC_VER >= 1000) */
85         extern char _osfile[];
86 #endif  /* (_MSC_VER >= 1000) */
87
88 #define FOPEN                   0x01    /* file handle open */
89 #define FAPPEND                 0x20    /* file handle opened O_APPEND */
90 #define FDEV                    0x40    /* file handle refers to device */
91 #define FTEXT                   0x80    /* file handle is in text mode */
92
93 #define _STREAM_LOCKS   26              /* Table of stream locks */
94 #define _LAST_STREAM_LOCK  (_STREAM_LOCKS+_NSTREAM_-1)  /* Last stream lock */
95 #define _FH_LOCKS          (_LAST_STREAM_LOCK+1)        /* Table of fh locks */
96
97 /***
98 *int _patch_open_osfhandle(long osfhandle, int flags) - open C Runtime file handle
99 *
100 *Purpose:
101 *       This function allocates a free C Runtime file handle and associates
102 *       it with the Win32 HANDLE specified by the first parameter. This is a
103 *       temperary fix for WIN95's brain damage GetFileType() error on socket
104 *       we just bypass that call for socket
105 *
106 *Entry:
107 *       long osfhandle - Win32 HANDLE to associate with C Runtime file handle.
108 *       int flags      - flags to associate with C Runtime file handle.
109 *
110 *Exit:
111 *       returns index of entry in fh, if successful
112 *       return -1, if no free entry is found
113 *
114 *Exceptions:
115 *
116 *******************************************************************************/
117
118 int __cdecl
119 _patch_open_osfhandle(long osfhandle, int flags)
120 {
121     int fh;
122     char fileflags;             /* _osfile flags */
123
124     /* copy relevant flags from second parameter */
125     fileflags = FDEV;
126
127     if(flags & _O_APPEND)
128         fileflags |= FAPPEND;
129
130     if(flags & _O_TEXT)
131         fileflags |= FTEXT;
132
133     /* attempt to allocate a C Runtime file handle */
134     if((fh = _alloc_osfhnd()) == -1) {
135         errno = EMFILE;         /* too many open files */
136         _doserrno = 0L;         /* not an OS error */
137         return -1;              /* return error to caller */
138     }
139
140     /* the file is open. now, set the info in _osfhnd array */
141     _set_osfhnd(fh, osfhandle);
142
143     fileflags |= FOPEN;         /* mark as open */
144
145 #if (_MSC_VER >= 1000)
146     _osfile(fh) = fileflags;    /* set osfile entry */
147     _unlock_fhandle(fh);
148 #else
149     _osfile[fh] = fileflags;    /* set osfile entry */
150     _unlock(fh+_FH_LOCKS);              /* unlock handle */
151 #endif
152
153     return fh;                  /* return handle */
154 }
155 #endif  /* _M_IX86 */
156
157 #define SOCKETAPI PASCAL 
158
159 typedef SOCKET (SOCKETAPI *LPSOCKACCEPT)(SOCKET, struct sockaddr *, int *);
160 typedef int (SOCKETAPI *LPSOCKBIND)(SOCKET, const struct sockaddr *, int);
161 typedef int (SOCKETAPI *LPSOCKCLOSESOCKET)(SOCKET);
162 typedef int (SOCKETAPI *LPSOCKCONNECT)(SOCKET, const struct sockaddr *, int);
163 typedef int (SOCKETAPI *LPSOCKIOCTLSOCKET)(SOCKET, long, u_long *);
164 typedef int (SOCKETAPI *LPSOCKGETPEERNAME)(SOCKET, struct sockaddr *, int *);
165 typedef int (SOCKETAPI *LPSOCKGETSOCKNAME)(SOCKET, struct sockaddr *, int *);
166 typedef int (SOCKETAPI *LPSOCKGETSOCKOPT)(SOCKET, int, int, char *, int *);
167 typedef u_long (SOCKETAPI *LPSOCKHTONL)(u_long);
168 typedef u_short (SOCKETAPI *LPSOCKHTONS)(u_short);
169 typedef int (SOCKETAPI *LPSOCKLISTEN)(SOCKET, int);
170 typedef u_long (SOCKETAPI *LPSOCKNTOHL)(u_long);
171 typedef u_short (SOCKETAPI *LPSOCKNTOHS)(u_short);
172 typedef int (SOCKETAPI *LPSOCKRECV)(SOCKET, char *, int, int);
173 typedef int (SOCKETAPI *LPSOCKRECVFROM)(SOCKET, char *, int, int, struct sockaddr *, int *);
174 typedef int (SOCKETAPI *LPSOCKSELECT)(int, fd_set *, fd_set *, fd_set *, const struct timeval *);
175 typedef int (SOCKETAPI *LPSOCKSEND)(SOCKET, const char *, int, int);
176 typedef int (SOCKETAPI *LPSOCKSENDTO)(SOCKET, const char *, int, int, const struct sockaddr *, int);
177 typedef int (SOCKETAPI *LPSOCKSETSOCKOPT)(SOCKET, int, int, const char *, int);
178 typedef int (SOCKETAPI *LPSOCKSHUTDOWN)(SOCKET, int);
179 typedef SOCKET (SOCKETAPI *LPSOCKSOCKET)(int, int, int);
180 typedef char FAR *(SOCKETAPI *LPSOCKINETNTOA)(struct in_addr in);
181 typedef unsigned long (SOCKETAPI *LPSOCKINETADDR)(const char FAR * cp);
182
183
184 /* Database function prototypes */
185 typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYADDR)(const char *, int, int);
186 typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYNAME)(const char *);
187 typedef int (SOCKETAPI *LPSOCKGETHOSTNAME)(char *, int);
188 typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYPORT)(int, const char *);
189 typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYNAME)(const char *, const char *);
190 typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNUMBER)(int);
191 typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNAME)(const char *);
192
193 /* Microsoft Windows Extension function prototypes */
194 typedef int (SOCKETAPI *LPSOCKWSASTARTUP)(unsigned short, LPWSADATA);
195 typedef int (SOCKETAPI *LPSOCKWSACLEANUP)(void);
196 typedef int (SOCKETAPI *LPSOCKWSAGETLASTERROR)(void);
197 typedef int (SOCKETAPI *LPWSAFDIsSet)(SOCKET, fd_set *);
198
199 static HINSTANCE hWinSockDll = 0;
200 /* extern CRITICAL_SECTION csSock; */
201
202 static LPSOCKACCEPT paccept = 0;
203 static LPSOCKBIND pbind = 0;
204 static LPSOCKCLOSESOCKET pclosesocket = 0;
205 static LPSOCKCONNECT pconnect = 0;
206 static LPSOCKIOCTLSOCKET pioctlsocket = 0;
207 static LPSOCKGETPEERNAME pgetpeername = 0;
208 static LPSOCKGETSOCKNAME pgetsockname = 0;
209 static LPSOCKGETSOCKOPT pgetsockopt = 0;
210 static LPSOCKHTONL phtonl = 0;
211 static LPSOCKHTONS phtons = 0;
212 static LPSOCKLISTEN plisten = 0;
213 static LPSOCKNTOHL pntohl = 0;
214 static LPSOCKNTOHS pntohs = 0;
215 static LPSOCKRECV precv = 0;
216 static LPSOCKRECVFROM precvfrom = 0;
217 static LPSOCKSELECT pselect = 0;
218 static LPSOCKSEND psend = 0;
219 static LPSOCKSENDTO psendto = 0;
220 static LPSOCKSETSOCKOPT psetsockopt = 0;
221 static LPSOCKSHUTDOWN pshutdown = 0;
222 static LPSOCKSOCKET psocket = 0;
223 static LPSOCKGETHOSTBYADDR pgethostbyaddr = 0;
224 static LPSOCKGETHOSTBYNAME pgethostbyname = 0;
225 static LPSOCKGETHOSTNAME pgethostname = 0;
226 static LPSOCKGETSERVBYPORT pgetservbyport = 0;
227 static LPSOCKGETSERVBYNAME pgetservbyname = 0;
228 static LPSOCKGETPROTOBYNUMBER pgetprotobynumber = 0;
229 static LPSOCKGETPROTOBYNAME pgetprotobyname = 0;
230 static LPSOCKWSASTARTUP pWSAStartup = 0;
231 static LPSOCKWSACLEANUP pWSACleanup = 0;
232 static LPSOCKWSAGETLASTERROR pWSAGetLastError = 0;
233 static LPWSAFDIsSet pWSAFDIsSet = 0;
234 static LPSOCKINETNTOA pinet_ntoa = 0;
235 static LPSOCKINETADDR pinet_addr = 0;
236
237 __declspec(thread) struct servent myservent;
238
239
240 void *
241 GetAddress(HINSTANCE hInstance, char *lpFunctionName)
242 {
243     char buffer[512];
244     FARPROC proc = GetProcAddress(hInstance, lpFunctionName);
245     if(proc == 0) {
246         sprintf(buffer, "Unable to get address of %s in WSock32.dll", lpFunctionName);
247         CROAK(buffer);
248     }
249     return proc;
250 }
251
252 void
253 LoadWinSock(void)
254 {
255 /*  EnterCriticalSection(&csSock); */
256     if(hWinSockDll == NULL) {
257         HINSTANCE hLib = LoadLibrary("WSock32.DLL");
258         if(hLib == NULL)
259             CROAK("Could not load WSock32.dll\n");
260
261         paccept = (LPSOCKACCEPT)GetAddress(hLib, "accept");
262         pbind = (LPSOCKBIND)GetAddress(hLib, "bind");
263         pclosesocket = (LPSOCKCLOSESOCKET)GetAddress(hLib, "closesocket");
264         pconnect = (LPSOCKCONNECT)GetAddress(hLib, "connect");
265         pioctlsocket = (LPSOCKIOCTLSOCKET)GetAddress(hLib, "ioctlsocket");
266         pgetpeername = (LPSOCKGETPEERNAME)GetAddress(hLib, "getpeername");
267         pgetsockname = (LPSOCKGETSOCKNAME)GetAddress(hLib, "getsockname");
268         pgetsockopt = (LPSOCKGETSOCKOPT)GetAddress(hLib, "getsockopt");
269         phtonl = (LPSOCKHTONL)GetAddress(hLib, "htonl");
270         phtons = (LPSOCKHTONS)GetAddress(hLib, "htons");
271         plisten = (LPSOCKLISTEN)GetAddress(hLib, "listen");
272         pntohl = (LPSOCKNTOHL)GetAddress(hLib, "ntohl");
273         pntohs = (LPSOCKNTOHS)GetAddress(hLib, "ntohs");
274         precv = (LPSOCKRECV)GetAddress(hLib, "recv");
275         precvfrom = (LPSOCKRECVFROM)GetAddress(hLib, "recvfrom");
276         pselect = (LPSOCKSELECT)GetAddress(hLib, "select");
277         psend = (LPSOCKSEND)GetAddress(hLib, "send");
278         psendto = (LPSOCKSENDTO)GetAddress(hLib, "sendto");
279         psetsockopt = (LPSOCKSETSOCKOPT)GetAddress(hLib, "setsockopt");
280         pshutdown = (LPSOCKSHUTDOWN)GetAddress(hLib, "shutdown");
281         psocket = (LPSOCKSOCKET)GetAddress(hLib, "socket");
282         pgethostbyaddr = (LPSOCKGETHOSTBYADDR)GetAddress(hLib, "gethostbyaddr");
283         pgethostbyname = (LPSOCKGETHOSTBYNAME)GetAddress(hLib, "gethostbyname");
284         pgethostname = (LPSOCKGETHOSTNAME)GetAddress(hLib, "gethostname");
285         pgetservbyport = (LPSOCKGETSERVBYPORT)GetAddress(hLib, "getservbyport");
286         pgetservbyname = (LPSOCKGETSERVBYNAME)GetAddress(hLib, "getservbyname");
287         pgetprotobynumber = (LPSOCKGETPROTOBYNUMBER)GetAddress(hLib, "getprotobynumber");
288         pgetprotobyname = (LPSOCKGETPROTOBYNAME)GetAddress(hLib, "getprotobyname");
289         pWSAStartup = (LPSOCKWSASTARTUP)GetAddress(hLib, "WSAStartup");
290         pWSACleanup = (LPSOCKWSACLEANUP)GetAddress(hLib, "WSACleanup");
291         pWSAGetLastError = (LPSOCKWSAGETLASTERROR)GetAddress(hLib, "WSAGetLastError");
292         pWSAFDIsSet = (LPWSAFDIsSet)GetAddress(hLib, "__WSAFDIsSet");
293         pinet_addr = (LPSOCKINETADDR)GetAddress(hLib,"inet_addr");
294         pinet_ntoa = (LPSOCKINETNTOA)GetAddress(hLib,"inet_ntoa");
295
296         hWinSockDll = hLib;
297     }
298 /*  LeaveCriticalSection(&csSock); */
299 }
300
301 void
302 EndSockets(void)
303 {
304     if(hWinSockDll != NULL) {
305         pWSACleanup();
306         FreeLibrary(hWinSockDll);
307     }
308     hWinSockDll = NULL;
309 }
310
311 void
312 StartSockets(void) 
313 {
314     unsigned short version;
315     WSADATA retdata;
316     int ret;
317     int iSockOpt = SO_SYNCHRONOUS_NONALERT;
318
319     LoadWinSock();
320     /*
321      * initalize the winsock interface and insure that it is
322      * cleaned up at exit.
323      */
324     version = 0x101;
325     if(ret = pWSAStartup(version, &retdata))
326         CROAK("Unable to locate winsock library!\n");
327     if(retdata.wVersion != version)
328         CROAK("Could not find version 1.1 of winsock dll\n");
329
330     /* atexit((void (*)(void)) EndSockets); */
331
332 #ifdef USE_SOCKETS_AS_HANDLES
333     /*
334      * Enable the use of sockets as filehandles
335      */
336     psetsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
337                 (char *)&iSockOpt, sizeof(iSockOpt));
338 #endif  /* USE_SOCKETS_AS_HANDLES */
339 }
340
341
342 #ifndef USE_SOCKETS_AS_HANDLES
343 FILE *
344 myfdopen(int fd, char *mode)
345 {
346     FILE *fp;
347     char sockbuf[256];
348     int optlen = sizeof(sockbuf);
349     int retval;
350
351     if (hWinSockDll == 0)
352         LoadWinSock();
353
354     retval = pgetsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
355     if(retval == SOCKET_ERROR && pWSAGetLastError() == WSAENOTSOCK) {
356         return(_fdopen(fd, mode));
357     }
358
359     /*
360      * If we get here, then fd is actually a socket.
361      */
362     Newz(1601, fp, 1, FILE);
363     if(fp == NULL) {
364         errno = ENOMEM;
365         return NULL;
366     }
367
368     fp->_file = fd;
369     if(*mode == 'r')
370         fp->_flag = _IOREAD;
371     else
372         fp->_flag = _IOWRT;
373    
374     return fp;
375 }
376 #endif  /* USE_SOCKETS_AS_HANDLES */
377
378
379 u_long
380 win32_htonl(u_long hostlong)
381 {
382     if(hWinSockDll == 0)
383         LoadWinSock();
384
385     return phtonl(hostlong);
386 }
387
388 u_short
389 win32_htons(u_short hostshort)
390 {
391     if(hWinSockDll == 0)
392         LoadWinSock();
393
394     return phtons(hostshort);
395 }
396
397 u_long
398 win32_ntohl(u_long netlong)
399 {
400     if(hWinSockDll == 0)
401         LoadWinSock();
402
403     return pntohl(netlong);
404 }
405
406 u_short
407 win32_ntohs(u_short netshort)
408 {
409     if(hWinSockDll == 0)
410         LoadWinSock();
411
412     return pntohs(netshort);
413 }
414
415
416 #define SOCKET_TEST(x, y)       if(hWinSockDll == 0) StartSockets();\
417                                 if((x) == (y)) errno = pWSAGetLastError()
418
419 #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
420
421 SOCKET
422 win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
423 {
424     SOCKET r;
425
426     SOCKET_TEST((r = paccept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
427     return OPEN_SOCKET(r);
428 }
429
430 int
431 win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen)
432 {
433     int r;
434
435     SOCKET_TEST_ERROR(r = pbind(TO_SOCKET(s), addr, addrlen));
436     return r;
437 }
438
439 int
440 win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
441 {
442     int r;
443
444     SOCKET_TEST_ERROR(r = pconnect(TO_SOCKET(s), addr, addrlen));
445     return r;
446 }
447
448
449 int
450 win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen)
451 {
452     int r;
453
454     SOCKET_TEST_ERROR(r = pgetpeername(TO_SOCKET(s), addr, addrlen));
455     return r;
456 }
457
458 int
459 win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen)
460 {
461     int r;
462
463     SOCKET_TEST_ERROR(r = pgetsockname(TO_SOCKET(s), addr, addrlen));
464     return r;
465 }
466
467 int
468 win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen)
469 {
470     int r;
471
472     SOCKET_TEST_ERROR(r = pgetsockopt(TO_SOCKET(s), level, optname, optval, optlen));
473     return r;
474 }
475
476 int
477 win32_ioctlsocket(SOCKET s, long cmd, u_long *argp)
478 {
479     int r;
480
481     SOCKET_TEST_ERROR(r = pioctlsocket(TO_SOCKET(s), cmd, argp));
482     return r;
483 }
484
485 int
486 win32_listen(SOCKET s, int backlog)
487 {
488     int r;
489
490     SOCKET_TEST_ERROR(r = plisten(TO_SOCKET(s), backlog));
491     return r;
492 }
493
494 int
495 win32_recv(SOCKET s, char *buf, int len, int flags)
496 {
497     int r;
498
499     SOCKET_TEST_ERROR(r = precv(TO_SOCKET(s), buf, len, flags));
500     return r;
501 }
502
503 int
504 win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
505 {
506     int r;
507
508     SOCKET_TEST_ERROR(r = precvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen));
509     return r;
510 }
511
512 /* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */
513 int
514 win32_select(int nfds, int* rd, int* wr, int* ex, const struct timeval* timeout)
515 {
516     long r;
517     int dummy = 0;
518     int i, fd, bit, offset;
519     FD_SET nrd, nwr, nex,*prd,*pwr,*pex;
520
521     if (!rd)
522         rd = &dummy, prd = NULL;
523     else
524         prd = &nrd;
525     if (!wr)
526         wr = &dummy, pwr = NULL;
527     else
528         pwr = &nwr;
529     if (!ex)
530         ex = &dummy, pex = NULL;
531     else
532         pex = &nex;
533
534     FD_ZERO(&nrd);
535     FD_ZERO(&nwr);
536     FD_ZERO(&nex);
537     for (i = 0; i < nfds; i++) {
538         fd = TO_SOCKET(i);
539         bit = 1L<<(i % (sizeof(int)*8));
540         offset = i / (sizeof(int)*8);
541         if (rd[offset] & bit)
542             FD_SET(fd, &nrd);
543         if (wr[offset] & bit)
544             FD_SET(fd, &nwr);
545         if (ex[offset] & bit)
546             FD_SET(fd, &nex);
547     }
548
549     SOCKET_TEST_ERROR(r = pselect(nfds, prd, pwr, pex, timeout));
550
551     for (i = 0; i < nfds; i++) {
552         fd = TO_SOCKET(i);
553         bit = 1L<<(i % (sizeof(int)*8));
554         offset = i / (sizeof(int)*8);
555         if (rd[offset] & bit) {
556             if (!pWSAFDIsSet(fd, &nrd))
557                 rd[offset] &= ~bit;
558         }
559         if (wr[offset] & bit) {
560             if (!pWSAFDIsSet(fd, &nwr))
561                 wr[offset] &= ~bit;
562         }
563         if (ex[offset] & bit) {
564             if (!pWSAFDIsSet(fd, &nex))
565                 ex[offset] &= ~bit;
566         }
567     }
568     return r;
569 }
570
571 int
572 win32_send(SOCKET s, const char *buf, int len, int flags)
573 {
574     int r;
575
576     SOCKET_TEST_ERROR(r = psend(TO_SOCKET(s), buf, len, flags));
577     return r;
578 }
579
580 int
581 win32_sendto(SOCKET s, const char *buf, int len, int flags,
582              const struct sockaddr *to, int tolen)
583 {
584     int r;
585
586     SOCKET_TEST_ERROR(r = psendto(TO_SOCKET(s), buf, len, flags, to, tolen));
587     return r;
588 }
589
590 int
591 win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
592 {
593     int r;
594
595     SOCKET_TEST_ERROR(r = psetsockopt(TO_SOCKET(s), level, optname, optval, optlen));
596     return r;
597 }
598     
599 int
600 win32_shutdown(SOCKET s, int how)
601 {
602     int r;
603
604     SOCKET_TEST_ERROR(r = pshutdown(TO_SOCKET(s), how));
605     return r;
606 }
607
608 SOCKET
609 win32_socket(int af, int type, int protocol)
610 {
611     SOCKET s;
612
613 #ifndef USE_SOCKETS_AS_HANDLES
614     SOCKET_TEST(s = psocket(af, type, protocol), INVALID_SOCKET);
615 #else
616     if(hWinSockDll == 0)
617         StartSockets();
618
619     if((s = psocket(af, type, protocol)) == INVALID_SOCKET)
620         errno = pWSAGetLastError();
621     else
622         s = OPEN_SOCKET(s);
623 #endif  /* USE_SOCKETS_AS_HANDLES */
624
625     return s;
626 }
627
628 struct hostent *
629 win32_gethostbyaddr(const char *addr, int len, int type)
630 {
631     struct hostent *r;
632
633     SOCKET_TEST(r = pgethostbyaddr(addr, len, type), NULL);
634     return r;
635 }
636
637 struct hostent *
638 win32_gethostbyname(const char *name)
639 {
640     struct hostent *r;
641
642     SOCKET_TEST(r = pgethostbyname(name), NULL);
643     return r;
644 }
645
646 int
647 win32_gethostname(char *name, int len)
648 {
649     int r;
650
651     SOCKET_TEST_ERROR(r = pgethostname(name, len));
652     return r;
653 }
654
655 struct protoent *
656 win32_getprotobyname(const char *name)
657 {
658     struct protoent *r;
659
660     SOCKET_TEST(r = pgetprotobyname(name), NULL);
661     return r;
662 }
663
664 struct protoent *
665 win32_getprotobynumber(int num)
666 {
667     struct protoent *r;
668
669     SOCKET_TEST(r = pgetprotobynumber(num), NULL);
670     return r;
671 }
672
673 struct servent *
674 win32_getservbyname(const char *name, const char *proto)
675 {
676     struct servent *r;
677    
678     SOCKET_TEST(r = pgetservbyname(name, proto), NULL);
679     if (r) {
680         r = win32_savecopyservent(&myservent, r, proto);
681     }
682     return r;
683 }
684
685 struct servent *
686 win32_getservbyport(int port, const char *proto)
687 {
688     struct servent *r;
689
690     SOCKET_TEST(r = pgetservbyport(port, proto), NULL);
691     if (r) {
692         r = win32_savecopyservent(&myservent, r, proto);
693     }
694     return r;
695 }
696
697 char FAR *
698 win32_inet_ntoa(struct in_addr in)
699 {
700     if(hWinSockDll == 0)
701         LoadWinSock();
702
703     return pinet_ntoa(in);
704 }
705
706 unsigned long
707 win32_inet_addr(const char FAR *cp)
708 {
709     if(hWinSockDll == 0)
710         LoadWinSock();
711
712     return pinet_addr(cp);
713
714 }
715
716 /*
717  * Networking stubs
718  */
719 #undef CROAK 
720 #define CROAK croak
721
722 void
723 win32_endhostent() 
724 {
725     CROAK("endhostent not implemented!\n");
726 }
727
728 void
729 win32_endnetent()
730 {
731     CROAK("endnetent not implemented!\n");
732 }
733
734 void
735 win32_endprotoent()
736 {
737     CROAK("endprotoent not implemented!\n");
738 }
739
740 void
741 win32_endservent()
742 {
743     CROAK("endservent not implemented!\n");
744 }
745
746
747 struct netent *
748 win32_getnetent(void) 
749 {
750     CROAK("getnetent not implemented!\n");
751     return (struct netent *) NULL;
752 }
753
754 struct netent *
755 win32_getnetbyname(char *name) 
756 {
757     CROAK("getnetbyname not implemented!\n");
758     return (struct netent *)NULL;
759 }
760
761 struct netent *
762 win32_getnetbyaddr(long net, int type) 
763 {
764     CROAK("getnetbyaddr not implemented!\n");
765     return (struct netent *)NULL;
766 }
767
768 struct protoent *
769 win32_getprotoent(void) 
770 {
771     CROAK("getprotoent not implemented!\n");
772     return (struct protoent *) NULL;
773 }
774
775 struct servent *
776 win32_getservent(void) 
777 {
778     CROAK("getservent not implemented!\n");
779     return (struct servent *) NULL;
780 }
781
782 void
783 win32_sethostent(int stayopen)
784 {
785     CROAK("sethostent not implemented!\n");
786 }
787
788
789 void
790 win32_setnetent(int stayopen)
791 {
792     CROAK("setnetent not implemented!\n");
793 }
794
795
796 void
797 win32_setprotoent(int stayopen)
798 {
799     CROAK("setprotoent not implemented!\n");
800 }
801
802
803 void
804 win32_setservent(int stayopen)
805 {
806     CROAK("setservent not implemented!\n");
807 }
808
809