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