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

Last change on this file since 7041 was 7041, checked in by sandervl, 24 years ago

several updates + fixes

File size: 43.8 KB
Line 
1/* $Id: wsock32.cpp,v 1.42 2001-10-13 18:51:08 sandervl 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 optlen = sizeof(option);
755 option = 0;
756 ret = getsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)&option, &optlen);
757 if(ret == 0 && option != FALSE) {
758 *(u_short *)&buf[2] = len;
759 }
760 dprintf(("sending to %s", inet_ntoa(((sockaddr_in*)to)->sin_addr)));
761 ret = sendto(s, (char *)buf, len, flags, (struct sockaddr *)to, tolen);
762
763 if(ret == SOCKET_ERROR) {
764 WSASetLastError(wsaErrno());
765 }
766 else WSASetLastError(NO_ERROR);
767
768 //Reset FD_WRITE event flag for WSAAsyncSelect thread if one was created for this socket
769 EnableAsyncEvent(s, FD_WRITE);
770 return ret;
771}
772//******************************************************************************
773//******************************************************************************
774ODINFUNCTION5(int,OS2select,
775 int,nfds,
776 ws_fd_set *,readfds,
777 ws_fd_set *,writefds,
778 ws_fd_set *,exceptfds,
779 const struct timeval *,timeout)
780{
781 int ret, i, j;
782 int *sockets, *socktmp;
783 int nrread, nrwrite, nrexcept;
784 ULONG ttimeout;
785
786 WSASetLastError(NO_ERROR);
787
788 if(!fWSAInitialized) {
789 WSASetLastError(WSANOTINITIALISED);
790 return SOCKET_ERROR;
791 }
792 else
793 if(WSAIsBlocking()) {
794 WSASetLastError(WSAEINPROGRESS);
795 return SOCKET_ERROR;
796 }
797 else {
798 nrread = nrwrite = nrexcept = 0;
799 if(readfds) {
800 nrread += readfds->fd_count;
801 }
802 if(writefds) {
803 nrwrite += writefds->fd_count;
804 }
805 if(exceptfds) {
806 nrexcept += exceptfds->fd_count;
807 }
808#if 0
809 if(nrread + nrwrite + nrexcept == 0) {
810 dprintf(("ERROR: nrread + nrwrite + nrexcept == 0"));
811 WSASetLastError(WSAEINVAL);
812 return SOCKET_ERROR;
813 }
814#endif
815 if(timeout != NULL && (timeout->tv_sec < 0 || timeout->tv_usec < 0)) {
816 dprintf(("ERROR: timeout->tv_sec < 0 || timeout->tv_usec < 0"));
817 WSASetLastError(WSAEINVAL);
818 return SOCKET_ERROR;
819 }
820 if(timeout == NULL) {
821 ttimeout = -1L; // no timeout
822 }
823 else ttimeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
824
825 sockets = (int *)malloc(sizeof(int) * (nrread+nrwrite+nrexcept));
826 if(readfds) {
827 memcpy(&sockets[0], readfds->fd_array, nrread * sizeof(SOCKET));
828 }
829 if(writefds) {
830 memcpy(&sockets[nrread], writefds->fd_array, nrwrite * sizeof(SOCKET));
831 }
832 if(exceptfds) {
833 memcpy(&sockets[nrread+nrwrite], exceptfds->fd_array, nrexcept * sizeof(SOCKET));
834 }
835
836 ret = select(sockets, nrread, nrwrite, nrexcept, ttimeout);
837
838 if(ret == SOCKET_ERROR)
839 {
840 if(readfds != NULL)
841 readfds->fd_count = 0;
842
843 if(writefds != NULL)
844 writefds->fd_count = 0;
845
846 if(exceptfds != NULL)
847 exceptfds->fd_count = 0;
848
849 WSASetLastError(wsaErrno());
850 free(sockets);
851 return SOCKET_ERROR;
852 }
853
854 if(ret != 0) {
855 socktmp = sockets;
856 if(readfds != NULL) {
857 j = 0;
858 for(i=0;i<nrread;i++) {
859 if(socktmp[i] != -1) {
860 readfds->fd_array[i] = socktmp[i];
861 j++;
862 }
863 }
864 readfds->fd_count = j;
865 socktmp += nrread;
866 }
867
868 if(writefds != NULL) {
869 j = 0;
870 for(i=0;i<nrwrite;i++) {
871 if(socktmp[i] != -1) {
872 writefds->fd_array[i] = socktmp[i];
873 j++;
874 }
875 }
876 writefds->fd_count = j;
877 socktmp += nrwrite;
878 }
879 if(exceptfds != NULL) {
880 j = 0;
881 for(i=0;i<nrexcept;i++) {
882 if(socktmp[i] != -1) {
883 exceptfds->fd_array[i] = socktmp[i];
884 j++;
885 }
886 }
887 exceptfds->fd_count = j;
888 }
889 }
890 else {
891 if(readfds != NULL)
892 readfds->fd_count = 0;
893
894 if(writefds != NULL)
895 writefds->fd_count = 0;
896
897 if(exceptfds != NULL)
898 exceptfds->fd_count = 0;
899 }
900 free(sockets);
901 }
902 return ret;
903}
904//******************************************************************************
905//******************************************************************************
906ODINFUNCTION5(int,OS2setsockopt,
907 SOCKET,s,
908 int,level,
909 int,optname,
910 const char *,optval,
911 int,optlen)
912{
913 struct ws_linger *yy;
914 struct linger xx;
915 int ret;
916 ULONG size;
917 char *safeoptval;
918
919 if(!fWSAInitialized) {
920 dprintf(("WSA not initialized"));
921 WSASetLastError(WSANOTINITIALISED);
922 return SOCKET_ERROR;
923 }
924 else
925 if(WSAIsBlocking()) {
926 dprintf(("WSA is blocking"));
927 WSASetLastError(WSAEINPROGRESS);
928 return SOCKET_ERROR;
929 }
930 //SvL: The 16 bits TCP/IP stack doesn't like high addresses, so copy
931 // the option value(s) on the stack.
932 safeoptval = (char *)alloca(optlen);
933 if(safeoptval == NULL) {
934 DebugInt3();
935 WSASetLastError(WSAEFAULT);
936 return SOCKET_ERROR;
937 }
938 memcpy(safeoptval, optval, optlen);
939 optval = safeoptval;
940
941 if (level == SOL_SOCKET)
942 {
943 switch(optname)
944 {
945 case SO_DONTLINGER:
946 case SO_LINGER:
947 if(optlen < (int)sizeof(ws_linger))
948 {
949 dprintf(("SOL_SOCKET, SO_LINGER, optlen too small"));
950 WSASetLastError(WSAEFAULT);
951 return SOCKET_ERROR;
952 }
953 yy = (struct ws_linger *)optval;
954 xx.l_onoff = (optname == SO_DONTLINGER) ? !yy->l_onoff : yy->l_onoff;
955 xx.l_linger = yy->l_linger;
956
957 ret = setsockopt(s,level,optname,(char *)&xx, sizeof(xx));
958 break;
959 case SO_SNDBUF:
960 case SO_RCVBUF:
961 if(optlen < (int)sizeof(int))
962 {
963 dprintf(("SOL_SOCKET, SO_RCVBUF, optlen too small"));
964 WSASetLastError(WSAEFAULT);
965 return SOCKET_ERROR;
966 }
967
968 size = *(ULONG *)optval;
969tryagain:
970 ret = setsockopt(s,level,optname, (char *)&size, sizeof(ULONG));
971 if(ret == SOCKET_ERROR && wsaErrno() == WSAENOBUFS && size > 4096) {
972 int newsize = (size > 65535) ? 63*1024 : (size-1024);
973 dprintf(("setsockopt: change size from %d to %d", size, newsize));
974 //SvL: Limit send & receive buffer length to 64k
975 // (only happens with 16 bits tcpip stack?)
976 size = newsize;
977 goto tryagain;
978 }
979 break;
980
981 case SO_BROADCAST:
982 case SO_DEBUG:
983 case SO_KEEPALIVE:
984 case SO_DONTROUTE:
985 case SO_OOBINLINE:
986 case SO_REUSEADDR:
987 if(optlen < (int)sizeof(int)) {
988 dprintf(("SOL_SOCKET, SO_REUSEADDR, optlen too small"));
989 WSASetLastError(WSAEFAULT);
990 return SOCKET_ERROR;
991 }
992 ret = setsockopt(s, level, optname, (char *)optval, optlen);
993 break;
994 default:
995 dprintf(("setsockopt: SOL_SOCKET, unknown option %x", optname));
996 WSASetLastError(WSAENOPROTOOPT);
997 return SOCKET_ERROR;
998 }
999 }
1000 else
1001 if(level == IPPROTO_TCP)
1002 {
1003 if(optname == TCP_NODELAY) {
1004 if(optlen < (int)sizeof(int)) {
1005 dprintf(("IPPROTO_TCP, TCP_NODELAY, optlen too small"));
1006 WSASetLastError(WSAEFAULT);
1007 return SOCKET_ERROR;
1008 }
1009 ret = setsockopt(s, level, optname, (char *)optval, optlen);
1010 }
1011 else {
1012 dprintf(("setsockopt: IPPROTO_TCP, unknown option %x", optname));
1013 WSASetLastError(WSAENOPROTOOPT);
1014 return SOCKET_ERROR;
1015 }
1016 }
1017 else
1018 if (level == IPPROTO_IP)
1019 {
1020 switch (optname)
1021 {
1022 case IP_MULTICAST_IF:
1023 case WS2_IPPROTO_OPT(IP_MULTICAST_IF_WS2):
1024 {
1025 if (optlen < sizeof(in_addr))
1026 {
1027 dprintf(("IPPROTO_IP, IP_MULTICAST_IP, optlen too small"));
1028 WSASetLastError(WSAEFAULT);
1029 return SOCKET_ERROR;
1030 }
1031 //TODO convert common interface names!
1032 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF_OS2, (char *)optval, optlen);
1033 break;
1034 }
1035
1036 case IP_ADD_MEMBERSHIP:
1037 case WS2_IPPROTO_OPT(IP_ADD_MEMBERSHIP_WS2):
1038 if (optlen < sizeof(struct ip_mreq))
1039 {
1040 dprintf(("IPPROTO_IP, IP_ADD_MEMBERSHIP, optlen too small"));
1041 WSASetLastError(WSAEFAULT);
1042 return SOCKET_ERROR;
1043 }
1044 ret = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP_OS2, (char *)optval, optlen);
1045 break;
1046
1047 case IP_DROP_MEMBERSHIP:
1048 case WS2_IPPROTO_OPT(IP_DROP_MEMBERSHIP_WS2):
1049 if (optlen < sizeof(struct ip_mreq))
1050 {
1051 dprintf(("IPPROTO_IP, IP_DROP_MEMBERSHIP, optlen too small"));
1052 WSASetLastError(WSAEFAULT);
1053 return SOCKET_ERROR;
1054 }
1055 ret = setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP_OS2, (char *)optval, optlen);
1056 break;
1057
1058 case IP_MULTICAST_LOOP:
1059 case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
1060 {
1061 u_int flLoop;
1062 if (optlen < sizeof(u_char))
1063 {
1064 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
1065 WSASetLastError(WSAEFAULT);
1066 return SOCKET_ERROR;
1067 }
1068 flLoop = (*optval == 0) ? 0 : 1;
1069 dprintf(("IP_MULTICAST_LOOP %d", *optval));
1070 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)&flLoop, optlen);
1071 break;
1072 }
1073
1074 case IP_MULTICAST_TTL:
1075 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
1076 if (optlen < sizeof(u_char))
1077 {
1078 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
1079 WSASetLastError(WSAEFAULT);
1080 return SOCKET_ERROR;
1081 }
1082 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
1083 break;
1084
1085 case IP_TTL:
1086 case WS2_IPPROTO_OPT(IP_TTL_WS2):
1087 if (optlen < sizeof(u_int))
1088 {
1089 dprintf(("IPPROTO_IP, IP_TTL_WS2, optlen too small"));
1090 WSASetLastError(WSAEFAULT);
1091 return SOCKET_ERROR;
1092 }
1093 dprintf(("IPPROTO_IP, IP_TTL 0x%x", *optval));
1094 ret = setsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
1095 break;
1096
1097 case IP_TOS:
1098 case WS2_IPPROTO_OPT(IP_TOS_WS2):
1099 if (optlen < sizeof(u_int))
1100 {
1101 dprintf(("IPPROTO_IP, IP_TOS_WS2, optlen too small"));
1102 WSASetLastError(WSAEFAULT);
1103 return SOCKET_ERROR;
1104 }
1105 dprintf(("IPPROTO_IP, IP_TOS 0x%x", *optval));
1106 ret = setsockopt(s, IPPROTO_IP, IP_TOS_OS2, (char *)optval, optlen);
1107 break;
1108
1109 case WS2_IPPROTO_OPT(IP_HDRINCL_WS2):
1110 if (optlen < sizeof(u_int))
1111 {
1112 dprintf(("IPPROTO_IP, IP_HDRINCL_WS2, optlen too small"));
1113 WSASetLastError(WSAEFAULT);
1114 return SOCKET_ERROR;
1115 }
1116 dprintf(("IPPROTO_IP, IP_HDRINCL 0x%x", *optval));
1117 ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)optval, optlen);
1118 break;
1119
1120 default:
1121 dprintf(("setsockopt: IPPROTO_IP, unknown option %x", optname));
1122 WSASetLastError(WSAENOPROTOOPT);
1123 return SOCKET_ERROR;
1124 }
1125 }
1126 else {
1127 dprintf(("unknown level code!"));
1128 WSASetLastError(WSAEINVAL);
1129 return SOCKET_ERROR;
1130 }
1131
1132 if(ret == SOCKET_ERROR) {
1133 WSASetLastError(wsaErrno());
1134 }
1135 else WSASetLastError(NO_ERROR);
1136 return ret;
1137}
1138//******************************************************************************
1139//******************************************************************************
1140ODINFUNCTION5(int,OS2getsockopt,
1141 SOCKET, s,
1142 int, level,
1143 int, optname,
1144 char *, optval,
1145 int *,optlen)
1146{
1147 struct ws_linger *yy;
1148 struct linger xx;
1149 int ret;
1150 int size, options;
1151
1152 if(!fWSAInitialized) {
1153 WSASetLastError(WSANOTINITIALISED);
1154 return SOCKET_ERROR;
1155 }
1156 else
1157 if(WSAIsBlocking()) {
1158 WSASetLastError(WSAEINPROGRESS);
1159 return SOCKET_ERROR;
1160 }
1161 if (level == SOL_SOCKET) {
1162 switch(optname) {
1163 case SO_DONTLINGER:
1164 case SO_LINGER:
1165 if(optlen == NULL || *optlen < sizeof(ws_linger)) {
1166 WSASetLastError(WSAEFAULT);
1167 return SOCKET_ERROR;
1168 }
1169 size = sizeof(xx);
1170 ret = getsockopt(s,level,optname,(char *)&xx, &size);
1171 yy = (struct ws_linger *)optval;
1172 yy->l_onoff = (optname == SO_DONTLINGER) ? !xx.l_onoff : xx.l_onoff;
1173 yy->l_linger = xx.l_linger;
1174 *optlen = size;
1175 break;
1176
1177 case SO_SNDBUF:
1178 case SO_RCVBUF:
1179 case SO_BROADCAST:
1180 case SO_DEBUG:
1181 case SO_KEEPALIVE:
1182 case SO_DONTROUTE:
1183 case SO_OOBINLINE:
1184 case SO_REUSEADDR:
1185 case SO_TYPE:
1186 if(optlen == NULL || *optlen < sizeof(int)) {
1187 WSASetLastError(WSAEFAULT);
1188 return SOCKET_ERROR;
1189 }
1190 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1191 break;
1192 case SO_ACCEPTCONN:
1193 if(optlen == NULL || *optlen < sizeof(int)) {
1194 WSASetLastError(WSAEFAULT);
1195 return SOCKET_ERROR;
1196 }
1197 size = sizeof(options);
1198 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS, (char *)&options, &size);
1199 if(ret != SOCKET_ERROR) {
1200 *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
1201 *optlen = sizeof(BOOL);
1202 }
1203 break;
1204 default:
1205 dprintf(("getsockopt: unknown option %x", optname));
1206 WSASetLastError(WSAENOPROTOOPT);
1207 return SOCKET_ERROR;
1208 }
1209 }
1210 else
1211 if(level == IPPROTO_TCP) {
1212 if(optname == TCP_NODELAY) {
1213 if(optlen == NULL || *optlen < sizeof(int)) {
1214 WSASetLastError(WSAEFAULT);
1215 return SOCKET_ERROR;
1216 }
1217 ret = getsockopt(s, level, optname, (char *)optval, optlen);
1218 }
1219 else {
1220 dprintf(("getsockopt: unknown option %x", optname));
1221 WSASetLastError(WSAENOPROTOOPT);
1222 return SOCKET_ERROR;
1223 }
1224 }
1225 else
1226 if(level == IPPROTO_IP) {
1227 switch (optname)
1228 {
1229 case IP_MULTICAST_IF:
1230 case WS2_IPPROTO_OPT(IP_MULTICAST_IF_WS2):
1231 {
1232 if (*optlen < sizeof(in_addr))
1233 {
1234 dprintf(("IPPROTO_IP, IP_MULTICAST_IP, optlen too small"));
1235 WSASetLastError(WSAEFAULT);
1236 return SOCKET_ERROR;
1237 }
1238 //TODO convert common interface names!
1239 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_IF_OS2, (char *)optval, optlen);
1240 break;
1241 }
1242
1243 case IP_ADD_MEMBERSHIP:
1244 case WS2_IPPROTO_OPT(IP_ADD_MEMBERSHIP_WS2):
1245 if (*optlen < sizeof(struct ip_mreq))
1246 {
1247 dprintf(("IPPROTO_IP, IP_ADD_MEMBERSHIP, optlen too small"));
1248 WSASetLastError(WSAEFAULT);
1249 return SOCKET_ERROR;
1250 }
1251 ret = getsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP_OS2, (char *)optval, optlen);
1252 break;
1253
1254 case IP_DROP_MEMBERSHIP:
1255 case WS2_IPPROTO_OPT(IP_DROP_MEMBERSHIP_WS2):
1256 if (*optlen < sizeof(struct ip_mreq))
1257 {
1258 dprintf(("IPPROTO_IP, IP_DROP_MEMBERSHIP, optlen too small"));
1259 WSASetLastError(WSAEFAULT);
1260 return SOCKET_ERROR;
1261 }
1262 ret = getsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP_OS2, (char *)optval, optlen);
1263 break;
1264
1265 case IP_MULTICAST_LOOP:
1266 case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
1267 {
1268 if (*optlen < sizeof(u_char))
1269 {
1270 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
1271 WSASetLastError(WSAEFAULT);
1272 return SOCKET_ERROR;
1273 }
1274 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)optval, optlen);
1275 break;
1276 }
1277
1278 case IP_MULTICAST_TTL:
1279 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
1280 if (*optlen < sizeof(u_char))
1281 {
1282 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
1283 WSASetLastError(WSAEFAULT);
1284 return SOCKET_ERROR;
1285 }
1286 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
1287 break;
1288
1289 case IP_TTL:
1290 case WS2_IPPROTO_OPT(IP_TTL_WS2):
1291 if (*optlen < sizeof(u_int))
1292 {
1293 dprintf(("IPPROTO_IP, IP_TTL_WS2, optlen too small"));
1294 WSASetLastError(WSAEFAULT);
1295 return SOCKET_ERROR;
1296 }
1297 ret = getsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
1298 break;
1299
1300 case IP_TOS:
1301 case WS2_IPPROTO_OPT(IP_TOS_WS2):
1302 if (*optlen < sizeof(u_int))
1303 {
1304 dprintf(("IPPROTO_IP, IP_TOS_WS2, optlen too small"));
1305 WSASetLastError(WSAEFAULT);
1306 return SOCKET_ERROR;
1307 }
1308 ret = getsockopt(s, IPPROTO_IP, IP_TOS_OS2, (char *)optval, optlen);
1309 break;
1310
1311 case WS2_IPPROTO_OPT(IP_HDRINCL_WS2):
1312 if (*optlen < sizeof(u_int))
1313 {
1314 dprintf(("IPPROTO_IP, IP_HDRINCL_WS2, optlen too small"));
1315 WSASetLastError(WSAEFAULT);
1316 return SOCKET_ERROR;
1317 }
1318 ret = getsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)optval, optlen);
1319 if(ret == 0) {
1320 ret = (ret != FALSE) ? TRUE : FALSE;
1321 }
1322 break;
1323
1324 default:
1325 dprintf(("getsockopt: IPPROTO_IP, unknown option %x", optname));
1326 WSASetLastError(WSAENOPROTOOPT);
1327 return SOCKET_ERROR;
1328 }
1329 }
1330 else {
1331 WSASetLastError(WSAEINVAL);
1332 return SOCKET_ERROR;
1333 }
1334
1335 if(ret == SOCKET_ERROR) {
1336 WSASetLastError(wsaErrno());
1337 }
1338 else WSASetLastError(NO_ERROR);
1339 return ret;
1340}
1341//******************************************************************************
1342//******************************************************************************
1343/* Database function prototypes */
1344//******************************************************************************
1345//******************************************************************************
1346ODINFUNCTION2(int,OS2gethostname,
1347 char *,name,
1348 int,namelen)
1349{
1350 int ret;
1351
1352 ret = gethostname(name, namelen);
1353 if(ret == NULL) {
1354 WSASetLastError(NO_ERROR);
1355 return 0;
1356 }
1357 WSASetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
1358 return SOCKET_ERROR;
1359}
1360//******************************************************************************
1361//******************************************************************************
1362ODINFUNCTION3(ws_hostent *,OS2gethostbyaddr,
1363 const char *,addr,
1364 int,len,
1365 int,type)
1366{
1367 LPWSINFO pwsi = WINSOCK_GetIData();
1368
1369 if( pwsi )
1370 {
1371 struct hostent* host;
1372 if( (host = gethostbyaddr((char *)addr, len, type)) != NULL ) {
1373 if( WS_dup_he(pwsi, host) ) {
1374 WSASetLastError(NO_ERROR);
1375 return pwsi->he;
1376 }
1377 else WSASetLastError(WSAENOBUFS);
1378 }
1379 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1380 }
1381 else WSASetLastError(WSANOTINITIALISED);
1382 return NULL;
1383}
1384//******************************************************************************
1385//******************************************************************************
1386ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
1387 const char *,name)
1388{
1389 LPWSINFO pwsi = WINSOCK_GetIData();
1390
1391 if( pwsi )
1392 {
1393 struct hostent* host;
1394
1395 USHORT sel = RestoreOS2FS();
1396 host = gethostbyname( (char*) name);
1397 SetFS(sel);
1398
1399 if( host != NULL )
1400 {
1401 if( WS_dup_he(pwsi, host) )
1402 {
1403 WSASetLastError(NO_ERROR);
1404 return pwsi->he;
1405 }
1406 else
1407 WSASetLastError(WSAENOBUFS);
1408 }
1409 else
1410 WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1411 }
1412 else
1413 WSASetLastError(WSANOTINITIALISED);
1414
1415 return NULL;
1416}
1417//******************************************************************************
1418//******************************************************************************
1419ODINFUNCTION2(struct ws_servent *,OS2getservbyport,
1420 int, port,
1421 const char *, proto)
1422{
1423 LPWSINFO pwsi = WINSOCK_GetIData();
1424
1425 if( pwsi )
1426 {
1427 struct servent* serv;
1428 if( (serv = getservbyport(port, (char *)proto)) != NULL ) {
1429 if( WS_dup_se(pwsi, serv) ) {
1430 WSASetLastError(NO_ERROR);
1431 return pwsi->se;
1432 }
1433 else WSASetLastError(WSAENOBUFS);
1434 }
1435 else WSASetLastError(WSANO_DATA);
1436 }
1437 else WSASetLastError(WSANOTINITIALISED);
1438 return NULL;
1439}
1440//******************************************************************************
1441//******************************************************************************
1442ODINFUNCTION2(struct ws_servent *,OS2getservbyname,
1443 const char *, name,
1444 const char *, proto)
1445{
1446 LPWSINFO pwsi = WINSOCK_GetIData();
1447
1448 if( pwsi )
1449 {
1450 struct servent *serv;
1451 if( (serv = getservbyname((char *)name, (char *)proto)) != NULL ) {
1452 if( WS_dup_se(pwsi, serv) ) {
1453 WSASetLastError(NO_ERROR);
1454 return pwsi->se;
1455 }
1456 else WSASetLastError(WSAENOBUFS);
1457 }
1458 else WSASetLastError(WSANO_DATA);
1459 }
1460 else WSASetLastError(WSANOTINITIALISED);
1461 return NULL;
1462}
1463//******************************************************************************
1464//******************************************************************************
1465ODINFUNCTION1(struct ws_protoent *,OS2getprotobynumber,
1466 int,number)
1467{
1468 LPWSINFO pwsi = WINSOCK_GetIData();
1469
1470 if( pwsi )
1471 {
1472 struct protoent* proto;
1473 if( (proto = getprotobynumber(number)) != NULL ) {
1474 if( WS_dup_pe(pwsi, proto) ) {
1475 WSASetLastError(NO_ERROR);
1476 return pwsi->pe;
1477 }
1478 else WSASetLastError(WSAENOBUFS);
1479 }
1480 else WSASetLastError(WSANO_DATA);
1481 }
1482 else WSASetLastError(WSANOTINITIALISED);
1483 return NULL;
1484}
1485//******************************************************************************
1486//******************************************************************************
1487ODINFUNCTION1(struct ws_protoent *,OS2getprotobyname,
1488 const char *,name)
1489{
1490 LPWSINFO pwsi = WINSOCK_GetIData();
1491
1492 if( pwsi )
1493 {
1494 struct protoent * proto;
1495 if( (proto = getprotobyname((char *)name)) != NULL ) {
1496 if(WS_dup_pe(pwsi, proto)) {
1497 WSASetLastError(NO_ERROR);
1498 return pwsi->pe;
1499 }
1500 else WSASetLastError(WSAENOBUFS);
1501 }
1502 else WSASetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1503 }
1504 else WSASetLastError(WSANOTINITIALISED);
1505 return NULL;
1506}
1507//******************************************************************************
1508//******************************************************************************
Note: See TracBrowser for help on using the repository browser.