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.
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.
11 #define WIN32_LEAN_AND_MEAN
14 #include <sys/socket.h>
21 #ifdef USE_SOCKETS_AS_HANDLES
22 // thanks to Beverly Brown (beverly@datacube.com)
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)
28 # define OPEN_SOCKET(x) _open_osfhandle(x,_O_RDWR|_O_BINARY)
30 # define TO_SOCKET(x) _get_osfhandle(x)
34 # define OPEN_SOCKET(x) (x)
35 # define TO_SOCKET(x) (x)
37 #endif // USE_SOCKETS_AS_HANDLES
40 // This is a clone of fdopen so that we can handle the version of sockets that NT gets to use.
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.
49 #if defined(_WIN32) && !defined(WIN95_OSFHANDLE_FIXED) && defined(_M_IX86)
52 #define EXT_C_FUNC extern "C"
54 #define EXT_C_FUNC extern
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);
64 #if (_MSC_VER >= 1000)
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)
72 CRITICAL_SECTION lock;
73 #endif /* defined (_MT) && !defined (DLL_FOR_WIN32S) */
76 EXT_C_FUNC ioinfo * __pioinfo[];
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)
83 extern "C" extern char _osfile[];
84 #endif // (_MSC_VER >= 1000)
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
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
96 *int _patch_open_osfhandle(long osfhandle, int flags) - open C Runtime file handle
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
105 * long osfhandle - Win32 HANDLE to associate with C Runtime file handle.
106 * int flags - flags to associate with C Runtime file handle.
109 * returns index of entry in fh, if successful
110 * return -1, if no free entry is found
114 *******************************************************************************/
116 int __cdecl _patch_open_osfhandle(long osfhandle, int flags)
119 char fileflags; // _osfile flags
121 // copy relevant flags from second parameter
124 if(flags & _O_APPEND)
125 fileflags |= FAPPEND;
130 // attempt to allocate a C Runtime file handle
131 if((fh = _alloc_osfhnd()) == -1)
133 errno = EMFILE; // too many open files
134 _doserrno = 0L; // not an OS error
135 return -1; // return error to caller
138 // the file is open. now, set the info in _osfhnd array
139 _set_osfhnd(fh, osfhandle);
141 fileflags |= FOPEN; // mark as open
143 #if (_MSC_VER >= 1000)
144 _osfile(fh) = fileflags; // set osfile entry
147 _osfile[fh] = fileflags; // set osfile entry
148 _unlock(fh+_FH_LOCKS); // unlock handle
152 return fh; // return handle
156 #define SOCKETAPI PASCAL
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);
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 *);
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 *);
198 static HINSTANCE hWinSockDll = 0;
199 // extern CRITICAL_SECTION csSock;
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;
236 __declspec(thread) struct servent myservent;
239 void *GetAddress(HINSTANCE hInstance, char *lpFunctionName)
242 FARPROC proc = GetProcAddress(hInstance, lpFunctionName);
245 sprintf(buffer, "Unable to get address of %s in WSock32.dll", lpFunctionName);
251 void LoadWinSock(void)
253 // EnterCriticalSection(&csSock);
254 if(hWinSockDll == NULL)
256 HINSTANCE hLib = LoadLibrary("WSock32.DLL");
258 CROAK("Could not load WSock32.dll\n");
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");
297 // LeaveCriticalSection(&csSock);
300 void EndSockets(void)
302 if(hWinSockDll != NULL)
305 FreeLibrary(hWinSockDll);
310 void StartSockets(void)
312 unsigned short version;
315 int iSockOpt = SO_SYNCHRONOUS_NONALERT;
319 // initalize the winsock interface and insure that it is
320 // cleaned up at exit.
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");
328 // atexit((void (*)(void)) EndSockets);
330 #ifdef USE_SOCKETS_AS_HANDLES
332 // Enable the use of sockets as filehandles
334 psetsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&iSockOpt, sizeof(iSockOpt));
335 #endif // USE_SOCKETS_AS_HANDLES
339 #ifndef USE_SOCKETS_AS_HANDLES
340 FILE *myfdopen(int fd, char *mode)
344 int optlen = sizeof(sockbuf);
351 retval = pgetsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
352 if(retval == SOCKET_ERROR && pWSAGetLastError() == WSAENOTSOCK)
354 return(_fdopen(fd, mode));
358 // If we get here, then fd is actually a socket.
360 Newz(1601, fp, 1, FILE);
375 #endif // USE_SOCKETS_AS_HANDLES
378 u_long win32_htonl(u_long hostlong)
383 return phtonl(hostlong);
386 u_short win32_htons(u_short hostshort)
391 return phtons(hostshort);
394 u_long win32_ntohl(u_long netlong)
399 return pntohl(netlong);
402 u_short win32_ntohs(u_short netshort)
407 return pntohs(netshort);
411 #define SOCKET_TEST(x, y) if(hWinSockDll == 0) StartSockets();\
412 if((x) == (y)) errno = pWSAGetLastError()
414 #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
416 SOCKET win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
420 SOCKET_TEST((r = paccept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
421 return OPEN_SOCKET(r);
424 int win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen)
428 SOCKET_TEST_ERROR(r = pbind(TO_SOCKET(s), addr, addrlen));
432 int win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
436 SOCKET_TEST_ERROR(r = pconnect(TO_SOCKET(s), addr, addrlen));
441 int win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen)
445 SOCKET_TEST_ERROR(r = pgetpeername(TO_SOCKET(s), addr, addrlen));
449 int win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen)
453 SOCKET_TEST_ERROR(r = pgetsockname(TO_SOCKET(s), addr, addrlen));
457 int win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen)
461 SOCKET_TEST_ERROR(r = pgetsockopt(TO_SOCKET(s), level, optname, optval, optlen));
465 int win32_ioctlsocket(SOCKET s, long cmd, u_long *argp)
469 SOCKET_TEST_ERROR(r = pioctlsocket(TO_SOCKET(s), cmd, argp));
473 int win32_listen(SOCKET s, int backlog)
477 SOCKET_TEST_ERROR(r = plisten(TO_SOCKET(s), backlog));
481 int win32_recv(SOCKET s, char *buf, int len, int flags)
485 SOCKET_TEST_ERROR(r = precv(TO_SOCKET(s), buf, len, flags));
489 int win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
493 SOCKET_TEST_ERROR(r = precvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen));
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)
502 int i, fd, bit, offset;
503 FD_SET nrd, nwr, nex,*prd,*pwr,*pex;
505 if (!rd) rd = &dummy, prd = NULL;
507 if (!wr) wr = &dummy, pwr = NULL;
509 if (!ex) ex = &dummy, pex = NULL;
515 for (i = 0; i < nfds; i++)
518 bit = 1L<<(i % (sizeof(int)*8));
519 offset = i / (sizeof(int)*8);
520 if (rd[offset] & bit)
522 if (wr[offset] & bit)
524 if (ex[offset] & bit)
528 SOCKET_TEST_ERROR(r = pselect(nfds, prd, pwr, pex, timeout));
530 for (i = 0; i < nfds; i++)
533 bit = 1L<<(i % (sizeof(int)*8));
534 offset = i / (sizeof(int)*8);
535 if (rd[offset] & bit)
537 if (!pWSAFDIsSet(fd, &nrd))
540 if (wr[offset] & bit)
542 if (!pWSAFDIsSet(fd, &nwr))
545 if (ex[offset] & bit)
547 if (!pWSAFDIsSet(fd, &nex))
554 int win32_send(SOCKET s, const char *buf, int len, int flags)
558 SOCKET_TEST_ERROR(r = psend(TO_SOCKET(s), buf, len, flags));
562 int win32_sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen)
566 SOCKET_TEST_ERROR(r = psendto(TO_SOCKET(s), buf, len, flags, to, tolen));
570 int win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
574 SOCKET_TEST_ERROR(r = psetsockopt(TO_SOCKET(s), level, optname, optval, optlen));
578 int win32_shutdown(SOCKET s, int how)
582 SOCKET_TEST_ERROR(r = pshutdown(TO_SOCKET(s), how));
586 SOCKET win32_socket(int af, int type, int protocol)
590 #ifndef USE_SOCKETS_AS_HANDLES
591 SOCKET_TEST(s = psocket(af, type, protocol), INVALID_SOCKET);
596 if((s = psocket(af, type, protocol)) == INVALID_SOCKET)
597 errno = pWSAGetLastError();
600 #endif // USE_SOCKETS_AS_HANDLES
605 struct hostent *win32_gethostbyaddr(const char *addr, int len, int type)
609 SOCKET_TEST(r = pgethostbyaddr(addr, len, type), NULL);
613 struct hostent *win32_gethostbyname(const char *name)
617 SOCKET_TEST(r = pgethostbyname(name), NULL);
621 int win32_gethostname(char *name, int len)
625 SOCKET_TEST_ERROR(r = pgethostname(name, len));
629 struct protoent *win32_getprotobyname(const char *name)
633 SOCKET_TEST(r = pgetprotobyname(name), NULL);
637 struct protoent *win32_getprotobynumber(int num)
641 SOCKET_TEST(r = pgetprotobynumber(num), NULL);
645 struct servent *win32_getservbyname(const char *name, const char *proto)
649 SOCKET_TEST(r = pgetservbyname(name, proto), NULL);
651 r = win32_savecopyservent(&myservent, r, proto);
656 struct servent *win32_getservbyport(int port, const char *proto)
660 SOCKET_TEST(r = pgetservbyport(port, proto), NULL);
662 r = win32_savecopyservent(&myservent, r, proto);
667 char FAR *win32_inet_ntoa(struct in_addr in)
669 if(hWinSockDll == 0) LoadWinSock();
671 return pinet_ntoa(in);
674 unsigned long win32_inet_addr(const char FAR *cp)
676 if(hWinSockDll == 0) LoadWinSock();
678 return pinet_addr(cp);
687 void win32_endhostent()
689 CROAK("endhostent not implemented!\n");
692 void win32_endnetent()
694 CROAK("endnetent not implemented!\n");
697 void win32_endprotoent()
699 CROAK("endprotoent not implemented!\n");
702 void win32_endservent()
704 CROAK("endservent not implemented!\n");
708 struct netent *win32_getnetent(void)
710 CROAK("getnetent not implemented!\n");
711 return (struct netent *) NULL;
714 struct netent *win32_getnetbyname(char *name)
716 CROAK("getnetbyname not implemented!\n");
717 return (struct netent *)NULL;
720 struct netent *win32_getnetbyaddr(long net, int type)
722 CROAK("getnetbyaddr not implemented!\n");
723 return (struct netent *)NULL;
726 struct protoent *win32_getprotoent(void)
728 CROAK("getprotoent not implemented!\n");
729 return (struct protoent *) NULL;
732 struct servent *win32_getservent(void)
734 CROAK("getservent not implemented!\n");
735 return (struct servent *) NULL;
738 void win32_sethostent(int stayopen)
740 CROAK("sethostent not implemented!\n");
744 void win32_setnetent(int stayopen)
746 CROAK("setnetent not implemented!\n");
750 void win32_setprotoent(int stayopen)
752 CROAK("setprotoent not implemented!\n");
756 void win32_setservent(int stayopen)
758 CROAK("setservent not implemented!\n");