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

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

get/setsockopt updates

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