source: trunk/src/wsock32/wsock32.cpp@ 7042

Last change on this file since 7042 was 7042, checked in by achimha, 24 years ago

added comment

File size: 44.0 KB
Line 
1/* $Id: wsock32.cpp,v 1.43 2001-10-13 19:04:39 achimha Exp $ */
2
3/*
4 *
5 * Project Odin Software License can be found in LICENSE.TXT
6 *
7 * Win32 SOCK32 for OS/2
8 *
9 * Copyright (C) 1999 Patrick Haller <phaller@gmx.net>
10 * Copyright (C) 2000 Sander van Leeuwen (sandervl@xs4all.nl)
11 *
12 * Some parts based on Wine code: (dlls\winsock\socket.c)
13 * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
14 *
15 */
16
17/* Remark:
18 * 1999/11/21 experimental rewrite using IBM's PMWSock only
19 * -> some structural differences remain! (hostent)
20 * 1999/12/01 experimental rewrite works (TELNET)
21 * -> open issue: WSASetLastError / WSAGetLastError
22 * call SetLastError / GetLastError according to docs
23 *
24 * 2000/22/03 Complete rewrite -> got rid of pmwsock
25 *
26 * identical structures:
27 * - sockaddr_in
28 * - WSADATA
29 * - sockaddr
30 * - fd_set
31 * - timeval
32 *
33 * incompatible structures:
34 * - hostent
35 * - netent
36 * - servent
37 * - protent
38 * - linger
39 */
40
41
42/*****************************************************************************
43 * Includes *
44 *****************************************************************************/
45
46#define INCL_BASE
47#include <os2wrap.h> //Odin32 OS/2 api wrappers
48
49#include <string.h>
50#include <odinwrap.h>
51#include <os2sel.h>
52#include <stdlib.h>
53#include <win32api.h>
54#define NO_DCDATA
55#include <winuser32.h>
56#include <wprocess.h>
57#include <misc.h>
58
59#include "wsock32.h"
60#include <ws2tcpip.h>
61#include "wsastruct.h"
62#include "asyncthread.h"
63
64#define DBG_LOCALLOG DBG_wsock32
65#include "dbglocal.h"
66
67//kso: dirty fix to make this compile! not permanent!
68BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER *p);
69#define LowPart u.LowPart
70
71
72ODINDEBUGCHANNEL(WSOCK32-WSOCK32)
73
74
75/*****************************************************************************
76 * Local variables *
77 *****************************************************************************/
78
79static LPWSINFO lpFirstIData = NULL;
80
81//******************************************************************************
82//******************************************************************************
83LPWSINFO WINSOCK_GetIData(HANDLE tid)
84{
85 LPWSINFO iData;
86 BOOL fCurrentThread = FALSE;
87
88 if(tid == CURRENT_THREAD) {
89 tid = GetCurrentThread();
90 fCurrentThread = TRUE;
91 }
92tryagain:
93 for (iData = lpFirstIData; iData; iData = iData->lpNextIData) {
94 if (iData->dwThisThread == tid)
95 break;
96 }
97 if(iData == NULL && fCurrentThread) {
98 WINSOCK_CreateIData();
99 fCurrentThread = FALSE; //just to prevent infinite loops
100 goto tryagain;
101 }
102 if(iData == NULL) {
103 dprintf(("WINSOCK_GetIData: couldn't find struct for thread %x", tid));
104 DebugInt3();// should never happen!!!!!!!
105 }
106 return iData;
107}
108//******************************************************************************
109//******************************************************************************
110BOOL WINSOCK_CreateIData(void)
111{
112 LPWSINFO iData;
113
114 iData = (LPWSINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WSINFO));
115 if (!iData)
116 return FALSE;
117 iData->dwThisThread = GetCurrentThread();
118 iData->lpNextIData = lpFirstIData;
119 lpFirstIData = iData;
120 return TRUE;
121}
122//******************************************************************************
123//******************************************************************************
124void WINSOCK_DeleteIData(void)
125{
126 LPWSINFO iData = WINSOCK_GetIData();
127 LPWSINFO* ppid;
128 if (iData) {
129 for (ppid = &lpFirstIData; *ppid; ppid = &(*ppid)->lpNextIData) {
130 if (*ppid == iData) {
131 *ppid = iData->lpNextIData;
132 break;
133 }
134 }
135
136 if( iData->flags & WSI_BLOCKINGCALL )
137 dprintf(("\tinside blocking call!\n"));
138
139 /* delete scratch buffers */
140 if(iData->he) free(iData->he);
141 if(iData->se) free(iData->se);
142 if(iData->pe) free(iData->pe);
143
144 //// if( iData->buffer ) SEGPTR_FREE(iData->buffer);
145 //// if( iData->dbuffer ) SEGPTR_FREE(iData->dbuffer);
146
147 HeapFree(GetProcessHeap(), 0, iData);
148 }
149}
150//******************************************************************************
151//******************************************************************************
152void WIN32API WSASetLastError(int iError)
153{
154#ifdef DEBUG
155 char msg[20];
156#endif
157 // according to the docs, WSASetLastError() is just a call-through
158 // to SetLastError()
159 SetLastError(iError);
160#ifdef DEBUG
161 switch (iError)
162 {
163 case NO_ERROR:
164 strcpy(msg, "no error");
165 break;
166 case WSAEINTR:
167 strcpy(msg, "WSAEINTR");
168 break;
169 case WSAEBADF:
170 strcpy(msg, "WSAEBADF");
171 break;
172 case WSAEACCES:
173 strcpy(msg, "WSAEACCES");
174 break;
175 case WSAEFAULT:
176 strcpy(msg, "WSAEFAULT");
177 break;
178 case WSAEINVAL:
179 strcpy(msg, "WSAEINVAL");
180 break;
181 case WSAEMFILE:
182 strcpy(msg, "WSAEMFILE");
183 break;
184 case WSAEWOULDBLOCK:
185 strcpy(msg, "WSAEWOULDBLOCK");
186 break;
187 case WSAEINPROGRESS:
188 strcpy(msg, "WSAEINPROGRESS");
189 break;
190 case WSAEALREADY:
191 strcpy(msg, "WSAEALREADY");
192 break;
193 default:
194 strcpy(msg, "unknown");
195 }
196 if (iError != 0)
197 {
198 dprintf(("WSASetLastError 0x%x - %s", iError, msg));
199 }
200#endif
201}
202//******************************************************************************
203//******************************************************************************
204int WIN32API WSAGetLastError()
205{
206 return GetLastError();
207}
208//******************************************************************************
209//******************************************************************************
210ODINFUNCTION2(int,OS2shutdown,
211 SOCKET,s,
212 int,how)
213{
214 int ret;
215
216 if(!fWSAInitialized) {
217 WSASetLastError(WSANOTINITIALISED);
218 return SOCKET_ERROR;
219 }
220 else
221 if(WSAIsBlocking()) {
222 WSASetLastError(WSAEINPROGRESS);
223 return SOCKET_ERROR;
224 }
225 ret = shutdown(s, how);
226
227 if(ret == SOCKET_ERROR) {
228 WSASetLastError(wsaErrno());
229 }
230 else WSASetLastError(NO_ERROR);
231 return ret;
232}
233//******************************************************************************
234//******************************************************************************
235ODINFUNCTION3(SOCKET,OS2socket,
236 int,af,
237 int,type,
238 int,protocol)
239{
240 SOCKET s;
241
242 if(!fWSAInitialized) {
243 WSASetLastError(WSANOTINITIALISED);
244 return SOCKET_ERROR;
245 }
246 else
247 if(WSAIsBlocking()) {
248 WSASetLastError(WSAEINPROGRESS);
249 return SOCKET_ERROR;
250 }
251 s = socket(af, type, protocol);
252
253 if(s == SOCKET_ERROR && sock_errno() == SOCEPFNOSUPPORT) {
254 //map SOCEPFNOSUPPORT to SOCEPFNOSUPPORT
255 WSASetLastError(SOCEPFNOSUPPORT);
256 }
257 else
258 if(s == SOCKET_ERROR) {
259 WSASetLastError(wsaErrno());
260 }
261 else WSASetLastError(NO_ERROR);
262 return s;
263}
264//******************************************************************************
265//******************************************************************************
266ODINFUNCTION1(int,OS2closesocket,SOCKET, s)
267{
268 int ret;
269
270 if(!fWSAInitialized) {
271 WSASetLastError(WSANOTINITIALISED);
272 return SOCKET_ERROR;
273 }
274 else
275 if(WSAIsBlocking()) {
276 WSASetLastError(WSAEINPROGRESS);
277 return SOCKET_ERROR;
278 }
279 //Close WSAAsyncSelect thread if one was created for this socket
280 FindAndSetAsyncEvent(s, WSA_SELECT_HWND, 0, 0, 0);
281
282 // wait thread termination
283 DosSleep(10);
284 ret = soclose(s);
285
286 if(ret == SOCKET_ERROR) {
287 WSASetLastError(wsaErrno());
288 }
289 else WSASetLastError(NO_ERROR);
290 return ret;
291}
292//******************************************************************************
293//******************************************************************************
294ODINFUNCTION3(int,OS2connect,
295 SOCKET, s,
296 const struct sockaddr *,name,
297 int, namelen)
298{
299 int ret;
300
301 if(!fWSAInitialized) {
302 WSASetLastError(WSANOTINITIALISED);
303 return SOCKET_ERROR;
304 }
305 else
306 if(WSAIsBlocking()) {
307 WSASetLastError(WSAEINPROGRESS);
308 return SOCKET_ERROR;
309 }
310 ret = connect(s, (sockaddr *)name, namelen);
311 // map BSD error codes
312 if(ret == SOCKET_ERROR) {
313 int sockerror = sock_errno();
314 if(sockerror && sockerror < SOCBASEERR) {
315 sockerror += SOCBASEERR;
316 }
317 if(sockerror == SOCEINPROGRESS) {
318 WSASetLastError(WSAEWOULDBLOCK);
319 }
320 else
321 if(sockerror == SOCEOPNOTSUPP) {
322 WSASetLastError(WSAEINVAL);
323 }
324 else WSASetLastError(wsaErrno());
325 }
326 else WSASetLastError(NO_ERROR);
327 return ret;
328}
329//******************************************************************************
330//******************************************************************************
331ODINFUNCTION3(int,OS2ioctlsocket,
332 SOCKET,s,
333 long, cmd,
334 u_long *,argp)
335{
336 int ret;
337
338 if(!fWSAInitialized) {
339 WSASetLastError(WSANOTINITIALISED);
340 return SOCKET_ERROR;
341 }
342 else
343 if(WSAIsBlocking()) {
344 WSASetLastError(WSAEINPROGRESS);
345 return SOCKET_ERROR;
346 }
347 // clear high word (not used in OS/2's tcpip stack)
348 cmd = LOUSHORT(cmd);
349
350 if(cmd != FIONBIO && cmd != FIONREAD && cmd != SIOCATMARK) {
351 WSASetLastError(WSAEINVAL);
352 return SOCKET_ERROR;
353 }
354
355 WSASetLastError(NO_ERROR);
356
357 //check if app want to set a socket, which has an outstanding async select,
358 //to blocking mode
359 if (cmd == FIONBIO) {
360 HWND hwnd;
361 int msg;
362 ULONG lEvent;
363
364 if(QueryAsyncEvent(s, &hwnd, &msg, &lEvent) == TRUE) {
365 if(*argp != 0) {
366 //nothing to do; already non-blocking
367 return NO_ERROR;
368 }
369 else
370 if(lEvent != 0) {
371 dprintf(("Trying to set socket to blocking mode while async select active -> return error!"));
372 WSASetLastError(WSAEINVAL);
373 return SOCKET_ERROR;
374 }
375 }
376 }
377 ret = ioctl(s, cmd, (char *)argp, sizeof(int));
378
379 // Map EOPNOTSUPP to EINVAL
380 int sockerror = sock_errno();
381 if(sockerror && sockerror < SOCBASEERR) {
382 sockerror += SOCBASEERR;
383 }
384
385 if(ret == SOCKET_ERROR && sockerror == SOCEOPNOTSUPP)
386 WSASetLastError(WSAEINVAL);
387 else
388 if(ret == SOCKET_ERROR) {
389 WSASetLastError(wsaErrno());
390 }
391 else WSASetLastError(NO_ERROR);
392 return ret;
393}
394//******************************************************************************
395//******************************************************************************
396ODINFUNCTION3(int,OS2getpeername,
397 SOCKET, s,
398 struct sockaddr *,name,
399 int *, namelen)
400{
401 int ret;
402
403 if(!fWSAInitialized) {
404 WSASetLastError(WSANOTINITIALISED);
405 return SOCKET_ERROR;
406 }
407 else
408 if(WSAIsBlocking()) {
409 WSASetLastError(WSAEINPROGRESS);
410 return SOCKET_ERROR;
411 }
412 else
413 if (namelen == NULL || *namelen < (int)sizeof(struct sockaddr_in)) {
414 WSASetLastError(WSAEFAULT);
415 return SOCKET_ERROR;
416 }
417 ret = getsockname(s, name, namelen);
418 if(ret == SOCKET_ERROR) {
419 WSASetLastError(wsaErrno());
420 }
421 else WSASetLastError(NO_ERROR);
422 return ret;
423}
424//******************************************************************************
425//******************************************************************************
426ODINFUNCTION3(int,OS2getsockname,
427 SOCKET,s,
428 struct sockaddr *,name,
429 int *, namelen)
430{
431 int ret;
432
433 if(!fWSAInitialized) {
434 WSASetLastError(WSANOTINITIALISED);
435 return SOCKET_ERROR;
436 }
437 else
438 if(WSAIsBlocking()) {
439 WSASetLastError(WSAEINPROGRESS);
440 return SOCKET_ERROR;
441 }
442 else
443 if (namelen == NULL || *namelen < (int)sizeof(struct sockaddr_in)) {
444 WSASetLastError(WSAEFAULT);
445 return SOCKET_ERROR;
446 }
447 ret = getsockname(s, name, namelen);
448 if(ret == SOCKET_ERROR) {
449 WSASetLastError(wsaErrno());
450 }
451 else WSASetLastError(NO_ERROR);
452 return ret;
453}
454//******************************************************************************
455//******************************************************************************
456ODINFUNCTION1(u_long,OS2htonl,
457 u_long,hostlong)
458{
459 return(htonl(hostlong));
460}
461//******************************************************************************
462//******************************************************************************
463ODINFUNCTION1(u_short,OS2htons,
464 u_short,hostshort)
465{
466 return(htons(hostshort));
467}
468//******************************************************************************
469//******************************************************************************
470ODINFUNCTION1(u_long,OS2ntohl,
471 u_long,netlong)
472{
473 return(ntohl(netlong));
474}
475//******************************************************************************
476//******************************************************************************
477ODINFUNCTION1(u_short,OS2ntohs,
478 u_short,netshort)
479{
480 return(ntohs(netshort));
481}
482//******************************************************************************
483//******************************************************************************
484ODINFUNCTION1(unsigned long,OS2inet_addr,
485 const char *, cp)
486{
487 dprintf(("WSOCK32: OS2inet_addr(%s)\n",
488 cp));
489
490 return (inet_addr((char *)cp));
491}
492//******************************************************************************
493//******************************************************************************
494ODINFUNCTION1(char *,OS2inet_ntoa,
495 struct in_addr, in)
496{
497 return(inet_ntoa(in));
498}
499//******************************************************************************
500//******************************************************************************
501ODINFUNCTION3(SOCKET,OS2accept, SOCKET, s,
502 struct sockaddr *,addr,
503 int *, addrlen)
504{
505 int ret, msg;
506 HWND hwnd;
507 ULONG lEvent;
508
509 if(!fWSAInitialized) {
510 WSASetLastError(WSANOTINITIALISED);
511 return SOCKET_ERROR;
512 }
513 else
514 if(WSAIsBlocking()) {
515 WSASetLastError(WSAEINPROGRESS);
516 return SOCKET_ERROR;
517 }
518 else
519 if ((addr != NULL) && (addrlen != NULL)) {
520 if (*addrlen < (int)sizeof(struct sockaddr_in)) {
521 WSASetLastError(WSAEFAULT);
522 return SOCKET_ERROR;
523 }
524 }
525 ret = accept(s, addr, addrlen);
526
527 if(ret != SOCKET_ERROR) {
528 //Enable FD_ACCEPT event flag if WSAAsyncSelect was called for this socket
529 EnableAsyncEvent(s, FD_ACCEPT);
530
531 //if this socket has an active async. select pending, then call WSAAsyncSelect
532 //with the same parameters for the new socket (see docs)
533 if(QueryAsyncEvent(s, &hwnd, &msg, &lEvent) == TRUE) {
534 if(WSAAsyncSelect(ret, hwnd, msg, lEvent) == SOCKET_ERROR) {
535 ret = SOCKET_ERROR;
536 }
537 }
538 }
539 if(ret == SOCKET_ERROR) {
540 WSASetLastError(wsaErrno());
541 }
542 else WSASetLastError(NO_ERROR);
543 return ret;
544}
545//******************************************************************************
546//******************************************************************************
547ODINFUNCTION3(int,OS2bind,
548 SOCKET ,s,
549 const struct sockaddr *,addr,
550 int, namelen)
551{
552 int ret;
553
554 if(!fWSAInitialized) {
555 WSASetLastError(WSANOTINITIALISED);
556 return SOCKET_ERROR;
557 }
558 else
559 if(WSAIsBlocking()) {
560 WSASetLastError(WSAEINPROGRESS);
561 return SOCKET_ERROR;
562 }
563 else
564 if(namelen < (int)sizeof(struct sockaddr_in)) {
565 WSASetLastError(WSAEFAULT);
566 return SOCKET_ERROR;
567 }
568 ret = bind(s, (struct sockaddr *)addr, namelen);
569
570 if(ret == SOCKET_ERROR) {
571 WSASetLastError(wsaErrno());
572 }
573 else WSASetLastError(NO_ERROR);
574 return ret;
575}
576//******************************************************************************
577//******************************************************************************
578ODINFUNCTION2(int,OS2listen,
579 SOCKET, s,
580 int, backlog)
581{
582 int ret, tmp, namelen;
583 struct sockaddr_in name;
584
585 if(!fWSAInitialized) {
586 WSASetLastError(WSANOTINITIALISED);
587 return SOCKET_ERROR;
588 }
589 else
590 if(WSAIsBlocking()) {
591 WSASetLastError(WSAEINPROGRESS);
592 return SOCKET_ERROR;
593 }
594 namelen = sizeof(name);
595 ret = getsockname(s, (struct sockaddr *)&name, &namelen);
596 if (ret == 0) {
597 if (name.sin_port == 0 && name.sin_addr.s_addr == 0) {
598 // Socket is not bound
599 WSASetLastError(WSAEINVAL);
600 return SOCKET_ERROR;
601 }
602 ret = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp)) &
603 (SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING);
604 if(ret) {
605 // Socket is already connected
606 WSASetLastError(WSAEISCONN);
607 return SOCKET_ERROR;
608 }
609 ret = listen(s, backlog);
610 //todo: reset FD_ACCEPT bit? (wine seems to do this, but it's not documented)
611 }
612 if(ret == SOCKET_ERROR) {
613 WSASetLastError(wsaErrno());
614 }
615 else WSASetLastError(NO_ERROR);
616 return ret;
617}
618//******************************************************************************
619//******************************************************************************
620ODINFUNCTION4(int,OS2recv,
621 SOCKET,s,
622 char *,buf,
623 int,len,
624 int,flags)
625{
626 int ret;
627
628 if(!fWSAInitialized) {
629 WSASetLastError(WSANOTINITIALISED);
630 return SOCKET_ERROR;
631 }
632 else
633 if(WSAIsBlocking()) {
634 WSASetLastError(WSAEINPROGRESS);
635 return SOCKET_ERROR;
636 }
637 ret = recv(s, buf, len, flags);
638
639 if(ret == SOCKET_ERROR) {
640 WSASetLastError(wsaErrno());
641 }
642 else
643 if(ret == 0) {
644 int tmp, state;
645
646 state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
647 if(state & SS_ISCONNECTED && flags != MSG_PEEK) {
648 dprintf(("recv returned 0, but socket is still connected -> return WSAWOULDBLOCK"));
649 WSASetLastError(WSAEWOULDBLOCK);
650 ret = 0; //graceful close
651 }
652 }
653 else WSASetLastError(NO_ERROR);
654
655 //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
656 EnableAsyncEvent(s, FD_READ);
657 return ret;
658}
659//******************************************************************************
660//******************************************************************************
661ODINFUNCTION6(int,OS2recvfrom,
662 SOCKET,s,
663 char *,buf,
664 int,len,
665 int,flags,
666 struct sockaddr *,from,
667 int *,fromlen)
668{
669 int ret;
670
671 if(!fWSAInitialized) {
672 WSASetLastError(WSANOTINITIALISED);
673 return SOCKET_ERROR;
674 }
675 else
676 if(WSAIsBlocking()) {
677 WSASetLastError(WSAEINPROGRESS);
678 return SOCKET_ERROR;
679 }
680 else
681 if(fromlen == NULL || *fromlen < (int)sizeof(struct sockaddr_in)) {
682 WSASetLastError(WSAEFAULT);
683 return SOCKET_ERROR;
684 }
685 ret = recvfrom(s, buf, len, flags, from, fromlen);
686
687 if(ret == SOCKET_ERROR) {
688 WSASetLastError(wsaErrno());
689 }
690 else WSASetLastError(NO_ERROR);
691
692 //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
693 EnableAsyncEvent(s, FD_READ);
694 return ret;
695}
696//******************************************************************************
697//******************************************************************************
698ODINFUNCTION4(int,OS2send,
699 SOCKET,s,
700 const char *,buf,
701 int,len,
702 int,flags)
703{
704 int ret;
705
706 if(!fWSAInitialized) {
707 WSASetLastError(WSANOTINITIALISED);
708 return SOCKET_ERROR;
709 }
710 else
711 if(WSAIsBlocking()) {
712 WSASetLastError(WSAEINPROGRESS);
713 return SOCKET_ERROR;
714 }
715 ret = send(s, (char *)buf, len, flags);
716
717 if(ret == SOCKET_ERROR) {
718 WSASetLastError(wsaErrno());
719 }
720 else WSASetLastError(NO_ERROR);
721
722 //Reset FD_WRITE event flagfor WSAAsyncSelect thread if one was created for this socket
723 EnableAsyncEvent(s, FD_WRITE);
724 return ret;
725}
726//******************************************************************************
727//******************************************************************************
728ODINFUNCTION6(int,OS2sendto,
729 SOCKET,s,
730 const char *,buf,
731 int,len,
732 int,flags,
733 const struct sockaddr *,to,
734 int,tolen)
735{
736 int ret;
737 int optlen;
738 int option;
739
740 if(!fWSAInitialized) {
741 WSASetLastError(WSANOTINITIALISED);
742 return SOCKET_ERROR;
743 }
744 else
745 if(WSAIsBlocking()) {
746 WSASetLastError(WSAEINPROGRESS);
747 return SOCKET_ERROR;
748 }
749 else
750 if(tolen < (int)sizeof(struct sockaddr_in)) {
751 WSASetLastError(WSAEFAULT);
752 return SOCKET_ERROR;
753 }
754 // check if the socket is a raw socket and has the IP_HDRINCL switch
755 // if this is the case, we overwrite the IP header length field with
756 // the actual length because some apps tend to put in garbage in there
757 // and rely on Windows correcting this
758 optlen = sizeof(option);
759 option = 0;
760 ret = getsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)&option, &optlen);
761 if(ret == 0 && option != FALSE) {
762 *(u_short *)&buf[2] = len;
763 }
764 dprintf(("sending to %s", inet_ntoa(((sockaddr_in*)to)->sin_addr)));
765 ret = sendto(s, (char *)buf, len, flags, (struct sockaddr *)to, tolen);
766
767 if(ret == SOCKET_ERROR) {
768 WSASetLastError(wsaErrno());
769 }
770 else WSASetLastError(NO_ERROR);
771
772 //Reset FD_WRITE event flag for WSAAsyncSelect thread if one was created for this socket
773 EnableAsyncEvent(s, FD_WRITE);
774 return ret;
775}
776//******************************************************************************
777//******************************************************************************
778ODINFUNCTION5(int,OS2select,
779 int,nfds,
780 ws_fd_set *,readfds,
781 ws_fd_set *,writefds,
782 ws_fd_set *,exceptfds,
783 const struct timeval *,timeout)
784{
785 int ret, i, j;
786 int *sockets, *socktmp;
787 int nrread, nrwrite, nrexcept;
788 ULONG ttimeout;
789
790 WSASetLastError(NO_ERROR);
791
792 if(!fWSAInitialized) {
793 WSASetLastError(WSANOTINITIALISED);
794 return SOCKET_ERROR;
795 }
796 else
797 if(WSAIsBlocking()) {
798 WSASetLastError(WSAEINPROGRESS);
799 return SOCKET_ERROR;
800 }
801 else {
802 nrread = nrwrite = nrexcept = 0;
803 if(readfds) {
804 nrread += readfds->fd_count;
805 }
806 if(writefds) {
807 nrwrite += writefds->fd_count;
808 }
809 if(exceptfds) {
810 nrexcept += exceptfds->fd_count;
811 }
812#if 0
813 if(nrread + nrwrite + nrexcept == 0) {
814 dprintf(("ERROR: nrread + nrwrite + nrexcept == 0"));
815 WSASetLastError(WSAEINVAL);
816 return SOCKET_ERROR;
817 }
818#endif
819 if(timeout != NULL && (timeout->tv_sec < 0 || timeout->tv_usec < 0)) {
820 dprintf(("ERROR: timeout->tv_sec < 0 || timeout->tv_usec < 0"));
821 WSASetLastError(WSAEINVAL);
822 return SOCKET_ERROR;
823 }
824 if(timeout == NULL) {
825 ttimeout = -1L; // no timeout
826 }
827 else ttimeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
828
829 sockets = (int *)malloc(sizeof(int) * (nrread+nrwrite+nrexcept));
830 if(readfds) {
831 memcpy(&sockets[0], readfds->fd_array, nrread * sizeof(SOCKET));
832 }
833 if(writefds) {
834 memcpy(&sockets[nrread], writefds->fd_array, nrwrite * sizeof(SOCKET));
835 }
836 if(exceptfds) {
837 memcpy(&sockets[nrread+nrwrite], exceptfds->fd_array, nrexcept * sizeof(SOCKET));
838 }
839
840 ret = select(sockets, nrread, nrwrite, nrexcept, ttimeout);
841
842 if(ret == SOCKET_ERROR)
843 {
844 if(readfds != NULL)
845 readfds->fd_count = 0;
846
847 if(writefds != NULL)
848 writefds->fd_count = 0;
849
850 if(exceptfds != NULL)
851 exceptfds->fd_count = 0;
852
853 WSASetLastError(wsaErrno());
854 free(sockets);
855 return SOCKET_ERROR;
856 }
857
858 if(ret != 0) {
859 socktmp = sockets;
860 if(readfds != NULL) {
861 j = 0;
862 for(i=0;i<nrread;i++) {
863 if(socktmp[i] != -1) {
864 readfds->fd_array[i] = socktmp[i];
865 j++;
866 }
867 }
868 readfds->fd_count = j;
869 socktmp += nrread;
870 }
871
872 if(writefds != NULL) {
873 j = 0;
874 for(i=0;i<nrwrite;i++) {
875 if(socktmp[i] != -1) {
876 writefds->fd_array[i] = socktmp[i];
877 j++;
878 }
879 }
880 writefds->fd_count = j;
881 socktmp += nrwrite;
882 }
883 if(exceptfds != NULL) {
884 j = 0;
885 for(i=0;i<nrexcept;i++) {
886 if(socktmp[i] != -1) {
887 exceptfds->fd_array[i] = socktmp[i];
888 j++;
889 }
890 }
891 exceptfds->fd_count = j;
892 }
893 }
894 else {
895 if(readfds != NULL)
896 readfds->fd_count = 0;
897
898 if(writefds != NULL)
899 writefds->fd_count = 0;
900
901 if(exceptfds != NULL)
902 exceptfds->fd_count = 0;
903 }
904 free(sockets);
905 }
906 return ret;
907}
908//******************************************************************************
909//******************************************************************************
910ODINFUNCTION5(int,OS2setsockopt,
911 SOCKET,s,
912 int,level,
913 int,optname,
914 const char *,optval,
915 int,optlen)
916{
917 struct ws_linger *yy;
918 struct linger xx;
919 int ret;
920 ULONG size;
921 char *safeoptval;
922
923 if(!fWSAInitialized) {
924 dprintf(("WSA not initialized"));
925 WSASetLastError(WSANOTINITIALISED);
926 return SOCKET_ERROR;
927 }
928 else
929 if(WSAIsBlocking()) {
930 dprintf(("WSA is blocking"));
931 WSASetLastError(WSAEINPROGRESS);
932 return SOCKET_ERROR;
933 }
934 //SvL: The 16 bits TCP/IP stack doesn't like high addresses, so copy
935 // the option value(s) on the stack.
936 safeoptval = (char *)alloca(optlen);
937 if(safeoptval == NULL) {
938 DebugInt3();
939 WSASetLastError(WSAEFAULT);
940 return SOCKET_ERROR;
941 }
942 memcpy(safeoptval, optval, optlen);
943 optval = safeoptval;
944
945 if (level == SOL_SOCKET)
946 {
947 switch(optname)
948 {
949 case SO_DONTLINGER:
950 case SO_LINGER:
951 if(optlen < (int)sizeof(ws_linger))
952 {
953 dprintf(("SOL_SOCKET, SO_LINGER, optlen too small"));
954 WSASetLastError(WSAEFAULT);
955 return SOCKET_ERROR;
956 }
957 yy = (struct ws_linger *)optval;
958 xx.l_onoff = (optname == SO_DONTLINGER) ? !yy->l_onoff : yy->l_onoff;
959 xx.l_linger = yy->l_linger;
960
961 ret = setsockopt(s,level,optname,(char *)&xx, sizeof(xx));
962 break;
963 case SO_SNDBUF:
964 case SO_RCVBUF:
965 if(optlen < (int)sizeof(int))
966 {
967 dprintf(("SOL_SOCKET, SO_RCVBUF, optlen too small"));
968 WSASetLastError(WSAEFAULT);
969 return SOCKET_ERROR;
970 }
971
972 size = *(ULONG *)optval;
973tryagain:
974 ret = setsockopt(s,level,optname, (char *)&size, sizeof(ULONG));
975 if(ret == SOCKET_ERROR && wsaErrno() == WSAENOBUFS && size > 4096) {
976 int newsize = (size > 65535) ? 63*1024 : (size-1024);
977 dprintf(("setsockopt: change size from %d to %d", size, newsize));
978 //SvL: Limit send & receive buffer length to 64k
979 // (only happens with 16 bits tcpip stack?)
980 size = newsize;
981 goto tryagain;
982 }
983 break;
984
985 case SO_BROADCAST:
986 case SO_DEBUG:
987 case SO_KEEPALIVE:
988 case SO_DONTROUTE:
989 case SO_OOBINLINE:
990 case SO_REUSEADDR:
991 if(optlen < (int)sizeof(int)) {
992 dprintf(("SOL_SOCKET, SO_REUSEADDR, optlen too small"));
993 WSASetLastError(WSAEFAULT);
994 return SOCKET_ERROR;
995 }
996 ret = setsockopt(s, level, optname, (char *)optval, optlen);
997 break;
998 default:
999 dprintf(("setsockopt: SOL_SOCKET, unknown option %x", optname));
1000 WSASetLastError(WSAENOPROTOOPT);
1001 return SOCKET_ERROR;
1002 }
1003 }
1004 else
1005 if(level == IPPROTO_TCP)
1006 {
1007 if(optname == TCP_NODELAY) {
1008 if(optlen < (int)sizeof(int)) {
1009 dprintf(("IPPROTO_TCP, TCP_NODELAY, optlen too small"));
1010 WSASetLastError(WSAEFAULT);
1011 return SOCKET_ERROR;
1012 }
1013 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1014 }
1015 else {
1016 dprintf(("setsockopt: IPPROTO_TCP, unknown option %x", optname));
1017 WSASetLastError(WSAENOPROTOOPT);
1018 return SOCKET_ERROR;
1019 }
1020 }
1021 else
1022 if (level == IPPROTO_IP)
1023 {
1024 switch (optname)
1025 {
1026 case IP_MULTICAST_IF:
1027 case WS2_IPPROTO_OPT(IP_MULTICAST_IF_WS2):
1028 {
1029 if (optlen < sizeof(in_addr))
1030 {
1031 dprintf(("IPPROTO_IP, IP_MULTICAST_IP, optlen too small"));
1032 WSASetLastError(WSAEFAULT);
1033 return SOCKET_ERROR;
1034 }
1035 //TODO convert common interface names!
1036 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF_OS2, (char *)optval, optlen);
1037 break;
1038 }
1039
1040 case IP_ADD_MEMBERSHIP:
1041 case WS2_IPPROTO_OPT(IP_ADD_MEMBERSHIP_WS2):
1042 if (optlen < sizeof(struct ip_mreq))
1043 {
1044 dprintf(("IPPROTO_IP, IP_ADD_MEMBERSHIP, optlen too small"));
1045 WSASetLastError(WSAEFAULT);
1046 return SOCKET_ERROR;
1047 }
1048 ret = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP_OS2, (char *)optval, optlen);
1049 break;
1050
1051 case IP_DROP_MEMBERSHIP:
1052 case WS2_IPPROTO_OPT(IP_DROP_MEMBERSHIP_WS2):
1053 if (optlen < sizeof(struct ip_mreq))
1054 {
1055 dprintf(("IPPROTO_IP, IP_DROP_MEMBERSHIP, optlen too small"));
1056 WSASetLastError(WSAEFAULT);
1057 return SOCKET_ERROR;
1058 }
1059 ret = setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP_OS2, (char *)optval, optlen);
1060 break;
1061
1062 case IP_MULTICAST_LOOP:
1063 case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
1064 {
1065 u_int flLoop;
1066 if (optlen < sizeof(u_char))
1067 {
1068 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
1069 WSASetLastError(WSAEFAULT);
1070 return SOCKET_ERROR;
1071 }
1072 flLoop = (*optval == 0) ? 0 : 1;
1073 dprintf(("IP_MULTICAST_LOOP %d", *optval));
1074 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)&flLoop, optlen);
1075 break;
1076 }
1077
1078 case IP_MULTICAST_TTL:
1079 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
1080 if (optlen < sizeof(u_char))
1081 {
1082 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
1083 WSASetLastError(WSAEFAULT);
1084 return SOCKET_ERROR;
1085 }
1086 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
1087 break;
1088
1089 case IP_TTL:
1090 case WS2_IPPROTO_OPT(IP_TTL_WS2):
1091 if (optlen < sizeof(u_int))
1092 {
1093 dprintf(("IPPROTO_IP, IP_TTL_WS2, optlen too small"));
1094 WSASetLastError(WSAEFAULT);
1095 return SOCKET_ERROR;
1096 }
1097 dprintf(("IPPROTO_IP, IP_TTL 0x%x", *optval));
1098 ret = setsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
1099 break;
1100
1101 case IP_TOS:
1102 case WS2_IPPROTO_OPT(IP_TOS_WS2):
1103 if (optlen < sizeof(u_int))
1104 {
1105 dprintf(("IPPROTO_IP, IP_TOS_WS2, optlen too small"));
1106 WSASetLastError(WSAEFAULT);
1107 return SOCKET_ERROR;
1108 }
1109 dprintf(("IPPROTO_IP, IP_TOS 0x%x", *optval));
1110 ret = setsockopt(s, IPPROTO_IP, IP_TOS_OS2, (char *)optval, optlen);
1111 break;
1112
1113 case WS2_IPPROTO_OPT(IP_HDRINCL_WS2):
1114 if (optlen < sizeof(u_int))
1115 {
1116 dprintf(("IPPROTO_IP, IP_HDRINCL_WS2, optlen too small"));
1117 WSASetLastError(WSAEFAULT);
1118 return SOCKET_ERROR;
1119 }
1120 dprintf(("IPPROTO_IP, IP_HDRINCL 0x%x", *optval));
1121 ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)optval, optlen);
1122 break;
1123
1124 default:
1125 dprintf(("setsockopt: IPPROTO_IP, unknown option %x", optname));
1126 WSASetLastError(WSAENOPROTOOPT);
1127 return SOCKET_ERROR;
1128 }
1129 }
1130 else {
1131 dprintf(("unknown level code!"));
1132 WSASetLastError(WSAEINVAL);
1133 return SOCKET_ERROR;
1134 }
1135
1136 if(ret == SOCKET_ERROR) {
1137 WSASetLastError(wsaErrno());
1138 }
1139 else WSASetLastError(NO_ERROR);
1140 return ret;
1141}
1142//******************************************************************************
1143//******************************************************************************
1144ODINFUNCTION5(int,OS2getsockopt,
1145 SOCKET, s,
1146 int, level,
1147 int, optname,
1148 char *, optval,
1149 int *,optlen)
1150{
1151 struct ws_linger *yy;
1152 struct linger xx;
1153 int ret;
1154 int size, options;
1155
1156 if(!fWSAInitialized) {
1157 WSASetLastError(WSANOTINITIALISED);
1158 return SOCKET_ERROR;
1159 }
1160 else
1161 if(WSAIsBlocking()) {
1162 WSASetLastError(WSAEINPROGRESS);
1163 return SOCKET_ERROR;
1164 }
1165 if (level == SOL_SOCKET) {
1166 switch(optname) {
1167 case SO_DONTLINGER:
1168 case SO_LINGER:
1169 if(optlen == NULL || *optlen < sizeof(ws_linger)) {
1170 WSASetLastError(WSAEFAULT);
1171 return SOCKET_ERROR;
1172 }
1173 size = sizeof(xx);
1174 ret = getsockopt(s,level,optname,(char *)&xx, &size);
1175 yy = (struct ws_linger *)optval;
1176 yy->l_onoff = (optname == SO_DONTLINGER) ? !xx.l_onoff : xx.l_onoff;
1177 yy->l_linger = xx.l_linger;
1178 *optlen = size;
1179 break;
1180
1181 case SO_SNDBUF:
1182 case SO_RCVBUF:
1183 case SO_BROADCAST:
1184 case SO_DEBUG:
1185 case SO_KEEPALIVE:
1186 case SO_DONTROUTE:
1187 case SO_OOBINLINE:
1188 case SO_REUSEADDR:
1189 case SO_TYPE:
1190 if(optlen == NULL || *optlen < sizeof(int)) {
1191 WSASetLastError(WSAEFAULT);
1192 return SOCKET_ERROR;
1193 }
1194 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1195 break;
1196 case SO_ACCEPTCONN:
1197 if(optlen == NULL || *optlen < sizeof(int)) {
1198 WSASetLastError(WSAEFAULT);
1199 return SOCKET_ERROR;
1200 }
1201 size = sizeof(options);
1202 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS, (char *)&options, &size);
1203 if(ret != SOCKET_ERROR) {
1204 *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
1205 *optlen = sizeof(BOOL);
1206 }
1207 break;
1208 default:
1209 dprintf(("getsockopt: unknown option %x", optname));
1210 WSASetLastError(WSAENOPROTOOPT);
1211 return SOCKET_ERROR;
1212 }
1213 }
1214 else
1215 if(level == IPPROTO_TCP) {
1216 if(optname == TCP_NODELAY) {
1217 if(optlen == NULL || *optlen < sizeof(int)) {
1218 WSASetLastError(WSAEFAULT);
1219 return SOCKET_ERROR;
1220 }
1221 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1222 }
1223 else {
1224 dprintf(("getsockopt: unknown option %x", optname));
1225 WSASetLastError(WSAENOPROTOOPT);
1226 return SOCKET_ERROR;
1227 }
1228 }
1229 else
1230 if(level == IPPROTO_IP) {
1231 switch (optname)
1232 {
1233 case IP_MULTICAST_IF:
1234 case WS2_IPPROTO_OPT(IP_MULTICAST_IF_WS2):
1235 {
1236 if (*optlen < sizeof(in_addr))
1237 {
1238 dprintf(("IPPROTO_IP, IP_MULTICAST_IP, optlen too small"));
1239 WSASetLastError(WSAEFAULT);
1240 return SOCKET_ERROR;
1241 }
1242 //TODO convert common interface names!
1243 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_IF_OS2, (char *)optval, optlen);
1244 break;
1245 }
1246
1247 case IP_ADD_MEMBERSHIP:
1248 case WS2_IPPROTO_OPT(IP_ADD_MEMBERSHIP_WS2):
1249 if (*optlen < sizeof(struct ip_mreq))
1250 {
1251 dprintf(("IPPROTO_IP, IP_ADD_MEMBERSHIP, optlen too small"));
1252 WSASetLastError(WSAEFAULT);
1253 return SOCKET_ERROR;
1254 }
1255 ret = getsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP_OS2, (char *)optval, optlen);
1256 break;
1257
1258 case IP_DROP_MEMBERSHIP:
1259 case WS2_IPPROTO_OPT(IP_DROP_MEMBERSHIP_WS2):
1260 if (*optlen < sizeof(struct ip_mreq))
1261 {
1262 dprintf(("IPPROTO_IP, IP_DROP_MEMBERSHIP, optlen too small"));
1263 WSASetLastError(WSAEFAULT);
1264 return SOCKET_ERROR;
1265 }
1266 ret = getsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP_OS2, (char *)optval, optlen);
1267 break;
1268
1269 case IP_MULTICAST_LOOP:
1270 case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
1271 {
1272 if (*optlen < sizeof(u_char))
1273 {
1274 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
1275 WSASetLastError(WSAEFAULT);
1276 return SOCKET_ERROR;
1277 }
1278 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)optval, optlen);
1279 break;
1280 }
1281
1282 case IP_MULTICAST_TTL:
1283 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
1284 if (*optlen < sizeof(u_char))
1285 {
1286 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
1287 WSASetLastError(WSAEFAULT);
1288 return SOCKET_ERROR;
1289 }
1290 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
1291 break;
1292
1293 case IP_TTL:
1294 case WS2_IPPROTO_OPT(IP_TTL_WS2):
1295 if (*optlen < sizeof(u_int))
1296 {
1297 dprintf(("IPPROTO_IP, IP_TTL_WS2, optlen too small"));
1298 WSASetLastError(WSAEFAULT);
1299 return SOCKET_ERROR;
1300 }
1301 ret = getsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
1302 break;
1303
1304 case IP_TOS:
1305 case WS2_IPPROTO_OPT(IP_TOS_WS2):
1306 if (*optlen < sizeof(u_int))
1307 {
1308 dprintf(("IPPROTO_IP, IP_TOS_WS2, optlen too small"));
1309 WSASetLastError(WSAEFAULT);
1310 return SOCKET_ERROR;
1311 }
1312 ret = getsockopt(s, IPPROTO_IP, IP_TOS_OS2, (char *)optval, optlen);
1313 break;
1314
1315 case WS2_IPPROTO_OPT(IP_HDRINCL_WS2):
1316 if (*optlen < sizeof(u_int))
1317 {
1318 dprintf(("IPPROTO_IP, IP_HDRINCL_WS2, optlen too small"));
1319 WSASetLastError(WSAEFAULT);
1320 return SOCKET_ERROR;
1321 }
1322 ret = getsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)optval, optlen);
1323 if(ret == 0) {
1324 ret = (ret != FALSE) ? TRUE : FALSE;
1325 }
1326 break;
1327
1328 default:
1329 dprintf(("getsockopt: IPPROTO_IP, unknown option %x", optname));
1330 WSASetLastError(WSAENOPROTOOPT);
1331 return SOCKET_ERROR;
1332 }
1333 }
1334 else {
1335 WSASetLastError(WSAEINVAL);
1336 return SOCKET_ERROR;
1337 }
1338
1339 if(ret == SOCKET_ERROR) {
1340 WSASetLastError(wsaErrno());
1341 }
1342 else WSASetLastError(NO_ERROR);
1343 return ret;
1344}
1345//******************************************************************************
1346//******************************************************************************
1347/* Database function prototypes */
1348//******************************************************************************
1349//******************************************************************************
1350ODINFUNCTION2(int,OS2gethostname,
1351 char *,name,
1352 int,namelen)
1353{
1354 int ret;
1355
1356 ret = gethostname(name, namelen);
1357 if(ret == NULL) {
1358 WSASetLastError(NO_ERROR);
1359 return 0;
1360 }
1361 WSASetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
1362 return SOCKET_ERROR;
1363}
1364//******************************************************************************
1365//******************************************************************************
1366ODINFUNCTION3(ws_hostent *,OS2gethostbyaddr,
1367 const char *,addr,
1368 int,len,
1369 int,type)
1370{
1371 LPWSINFO pwsi = WINSOCK_GetIData();
1372
1373 if( pwsi )
1374 {
1375 struct hostent* host;
1376 if( (host = gethostbyaddr((char *)addr, len, type)) != NULL ) {
1377 if( WS_dup_he(pwsi, host) ) {
1378 WSASetLastError(NO_ERROR);
1379 return pwsi->he;
1380 }
1381 else WSASetLastError(WSAENOBUFS);
1382 }
1383 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1384 }
1385 else WSASetLastError(WSANOTINITIALISED);
1386 return NULL;
1387}
1388//******************************************************************************
1389//******************************************************************************
1390ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
1391 const char *,name)
1392{
1393 LPWSINFO pwsi = WINSOCK_GetIData();
1394
1395 if( pwsi )
1396 {
1397 struct hostent* host;
1398
1399 USHORT sel = RestoreOS2FS();
1400 host = gethostbyname( (char*) name);
1401 SetFS(sel);
1402
1403 if( host != NULL )
1404 {
1405 if( WS_dup_he(pwsi, host) )
1406 {
1407 WSASetLastError(NO_ERROR);
1408 return pwsi->he;
1409 }
1410 else
1411 WSASetLastError(WSAENOBUFS);
1412 }
1413 else
1414 WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1415 }
1416 else
1417 WSASetLastError(WSANOTINITIALISED);
1418
1419 return NULL;
1420}
1421//******************************************************************************
1422//******************************************************************************
1423ODINFUNCTION2(struct ws_servent *,OS2getservbyport,
1424 int, port,
1425 const char *, proto)
1426{
1427 LPWSINFO pwsi = WINSOCK_GetIData();
1428
1429 if( pwsi )
1430 {
1431 struct servent* serv;
1432 if( (serv = getservbyport(port, (char *)proto)) != NULL ) {
1433 if( WS_dup_se(pwsi, serv) ) {
1434 WSASetLastError(NO_ERROR);
1435 return pwsi->se;
1436 }
1437 else WSASetLastError(WSAENOBUFS);
1438 }
1439 else WSASetLastError(WSANO_DATA);
1440 }
1441 else WSASetLastError(WSANOTINITIALISED);
1442 return NULL;
1443}
1444//******************************************************************************
1445//******************************************************************************
1446ODINFUNCTION2(struct ws_servent *,OS2getservbyname,
1447 const char *, name,
1448 const char *, proto)
1449{
1450 LPWSINFO pwsi = WINSOCK_GetIData();
1451
1452 if( pwsi )
1453 {
1454 struct servent *serv;
1455 if( (serv = getservbyname((char *)name, (char *)proto)) != NULL ) {
1456 if( WS_dup_se(pwsi, serv) ) {
1457 WSASetLastError(NO_ERROR);
1458 return pwsi->se;
1459 }
1460 else WSASetLastError(WSAENOBUFS);
1461 }
1462 else WSASetLastError(WSANO_DATA);
1463 }
1464 else WSASetLastError(WSANOTINITIALISED);
1465 return NULL;
1466}
1467//******************************************************************************
1468//******************************************************************************
1469ODINFUNCTION1(struct ws_protoent *,OS2getprotobynumber,
1470 int,number)
1471{
1472 LPWSINFO pwsi = WINSOCK_GetIData();
1473
1474 if( pwsi )
1475 {
1476 struct protoent* proto;
1477 if( (proto = getprotobynumber(number)) != NULL ) {
1478 if( WS_dup_pe(pwsi, proto) ) {
1479 WSASetLastError(NO_ERROR);
1480 return pwsi->pe;
1481 }
1482 else WSASetLastError(WSAENOBUFS);
1483 }
1484 else WSASetLastError(WSANO_DATA);
1485 }
1486 else WSASetLastError(WSANOTINITIALISED);
1487 return NULL;
1488}
1489//******************************************************************************
1490//******************************************************************************
1491ODINFUNCTION1(struct ws_protoent *,OS2getprotobyname,
1492 const char *,name)
1493{
1494 LPWSINFO pwsi = WINSOCK_GetIData();
1495
1496 if( pwsi )
1497 {
1498 struct protoent * proto;
1499 if( (proto = getprotobyname((char *)name)) != NULL ) {
1500 if(WS_dup_pe(pwsi, proto)) {
1501 WSASetLastError(NO_ERROR);
1502 return pwsi->pe;
1503 }
1504 else WSASetLastError(WSAENOBUFS);
1505 }
1506 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1507 }
1508 else WSASetLastError(WSANOTINITIALISED);
1509 return NULL;
1510}
1511//******************************************************************************
1512//******************************************************************************
Note: See TracBrowser for help on using the repository browser.