Release 970720
[wine] / misc / winsock.c
1 /*
2  * based on Windows Sockets 1.1 specs
3  * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4  * 
5  * (C) 1993,1994,1996 John Brezak, Erik Bos, Alex Korobka.
6  *
7  * TODO: Merge Async...() handling with X event loop by adding 
8  *       thread/task fdset to select(2) in windows/event.c.
9  *       Also fork dns lookup helper during the startup (with a pipe 
10  *       for communication) and make it fork for a database request
11  *       instead of forking the main process (i.e. something like 
12  *       Netscape 4.0).
13  */
14  
15 #include <stdio.h>
16 #include <string.h>
17 #include <signal.h>
18 #include <sys/types.h>
19 #include <sys/ipc.h>
20 #include <sys/ioctl.h>
21 #if defined(__svr4__)
22 #include <sys/filio.h>
23 #include <sys/ioccom.h>
24 #include <sys/sockio.h>
25 #endif
26 #if defined(__EMX__)
27 #include <sys/so_ioctl.h>
28 #include <sys/param.h>
29 #endif
30 #include <sys/msg.h>
31 #include <sys/wait.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <netdb.h>
38 #include <unistd.h>
39
40 #include "windows.h"
41 #include "winnt.h"
42 #include "heap.h"
43 #include "ldt.h"
44 #include "winsock.h"
45 #include "stddebug.h"
46 #include "debug.h"
47
48 #define dump_sockaddr(a) \
49         fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
50                         ((struct sockaddr_in *)a)->sin_family, \
51                         inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
52                         ntohs(((struct sockaddr_in *)a)->sin_port))
53
54 extern void SIGNAL_MaskAsyncEvents( BOOL32 );
55
56 #pragma pack(4)
57
58 /* ----------------------------------- internal data */
59
60 extern int h_errno;
61 extern void __sigio(int);
62
63 ws_async_ctl            async_ctl;
64 int                     async_qid = -1;
65
66 static HANDLE32         _WSHeap = 0;
67 static unsigned char*   _ws_stub = NULL;
68 static LPWSINFO         _wsi_list = NULL;
69
70 #define WS_ALLOC(size) \
71         HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
72 #define WS_FREE(ptr) \
73         HeapFree(_WSHeap, 0, (ptr) )
74
75 #define WS_PTR2HANDLE(ptr) \
76         ((short)((int)(ptr) - (int)_ws_stub))
77 #define WS_HANDLE2PTR(handle) \
78         ((unsigned)((int)_ws_stub + (int)handle))
79
80 #define WSI_CHECK_RANGE(pwsi, pws) \
81         ( ((unsigned)(pws) > (unsigned)(pwsi)) && \
82           ((unsigned)(pws) < ((unsigned)(pwsi) + sizeof(WSINFO))) )
83
84 static INT16         _ws_sock_ops[] =
85        { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
86          WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
87          WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER, 0 };
88 static int           _px_sock_ops[] =
89        { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
90          SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
91          SO_LINGER };
92
93 static INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent);
94 static int notify_client(ws_socket* pws, unsigned flag);
95
96 static int _check_ws(LPWSINFO pwsi, ws_socket* pws);
97 static int _check_buffer(LPWSINFO pwsi, int size);
98
99 static void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base);
100 static void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base);
101 static void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base);
102
103 static int cancel_async_select(ws_socket*);
104
105 static void convert_sockopt(INT16 *level, INT16 *optname)
106 {
107   int           i;
108   switch (*level)
109   {
110      case WS_SOL_SOCKET:
111         *level = SOL_SOCKET;
112         for(i=0; _ws_sock_ops[i]; i++)
113             if( _ws_sock_ops[i] == *optname ) break;
114         if( _ws_sock_ops[i] ) *optname = (INT16)_px_sock_ops[i];
115         else fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
116         break;
117      case WS_IPPROTO_TCP:
118         *optname = IPPROTO_TCP;
119   }
120 }
121
122 static void _ws_global_init()
123 {
124    if( !_ws_stub )
125    {
126      _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
127      if( !(_ws_stub = WS_ALLOC(0x10)) )
128        fprintf(stderr,"Fatal: failed to create WinSock heap\n");
129    }
130    if( async_qid == -1 ) 
131      if( (async_qid = msgget(IPC_PRIVATE, IPC_CREAT | 0x1FF)) == -1 )
132        fprintf(stderr,"Fatal: failed to create WinSock resource\n");
133 }
134
135 /* ----------------------------------- Per-thread info */
136
137 static void wsi_link(LPWSINFO pwsi)
138 { if( _wsi_list ) _wsi_list->prev = pwsi;
139   pwsi->next = _wsi_list; _wsi_list = pwsi; 
140 }
141
142 static void wsi_unlink(LPWSINFO pwsi)
143 {
144   if( pwsi == _wsi_list ) _wsi_list = pwsi->next;
145   else 
146   { pwsi->prev->next = pwsi->next;
147     if( pwsi->next ) pwsi->next->prev = pwsi->prev; } 
148 }
149
150 static LPWSINFO wsi_find(HTASK16 hTask)
151 { LPWSINFO pwsi = _wsi_list;
152   while( pwsi && pwsi->tid != hTask ) pwsi = pwsi->next;
153   return pwsi; 
154 }
155
156 static ws_socket* wsi_alloc_socket(LPWSINFO pwsi, int fd)
157 {
158   if( pwsi->last_free >= 0 )
159   {
160     int i = pwsi->last_free;
161
162     pwsi->last_free = pwsi->sock[i].flags;
163     pwsi->sock[i].fd = fd;
164     pwsi->sock[i].flags = 0;
165     return &pwsi->sock[i];
166   }
167   return NULL;
168 }
169
170 static void fd_set_normalize(fd_set* fds, LPWSINFO pwsi, ws_fd_set* ws, int* highfd)
171 {
172   FD_ZERO(fds);
173   if(ws) 
174   { 
175     int         i;
176     ws_socket*  pws;
177     for(i=0;i<(ws->fd_count);i++) 
178     {
179       pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
180       if( _check_ws(pwsi, pws) ) 
181       { 
182         if( pws->fd > *highfd ) *highfd = pws->fd; 
183         FD_SET(pws->fd, fds); 
184       }
185     }
186   }
187 }
188
189 /*
190  * Note weirdness here: sockets with errors belong in exceptfds, but
191  * are given to us in readfds or writefds, so move them to exceptfds if
192  * there is an error. Note that this means that exceptfds may have mysterious
193  * sockets set in it that the program never asked for.
194  */
195
196 __inline__ static int sock_error_p(int s)
197 {
198     unsigned int optval, optlen;
199
200     optlen = sizeof(optval);
201     getsockopt(s, SOL_SOCKET, SO_ERROR, &optval, &optlen);
202     if (optval) dprintf_winsock(stddeb, "error: %d\n", optval);
203     return optval != 0;
204 }
205
206 static void fd_set_update(LPWSINFO pwsi, fd_set* fds, ws_fd_set* ws,
207                           fd_set *errorfds)
208 {
209     if( ws )
210     {
211         int i, j, count = ws->fd_count;
212
213         for( i = 0, j = 0; i < count; i++ )
214         {
215             ws_socket *pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
216             int fd = pws->fd;
217
218             if( _check_ws(pwsi, pws) && FD_ISSET(fd, fds) )
219             {
220                 /* if error, move to errorfds */
221                 if (errorfds && (FD_ISSET(fd, errorfds) || sock_error_p(fd)))
222                     FD_SET(fd, errorfds);
223                 else
224                     ws->fd_array[j++] = ws->fd_array[i];
225             }
226         }
227         ws->fd_count = j;
228         dprintf_winsock(stddeb, "\n");
229     }
230     return;
231 }
232
233 static void fd_set_update_except(LPWSINFO pwsi, fd_set *fds, ws_fd_set *ws,
234                                  fd_set *errorfds)
235 {
236     if (ws)
237     {
238         int i, j, count = ws->fd_count;
239
240         for (i=j=0; i < count; i++)
241         {
242             ws_socket *pws = (ws_socket *)WS_HANDLE2PTR(ws->fd_array[i]);
243
244             if (_check_ws(pwsi, pws) && (FD_ISSET(pws->fd, fds)
245                                          || FD_ISSET(pws->fd, errorfds)))
246             ws->fd_array[j++] = ws->fd_array[i];
247         }
248         ws->fd_count = j;
249     }
250     return;
251 }
252
253 /* ----------------------------------- API ----- 
254  *
255  * Init / cleanup / error checking.
256  */
257
258 INT16 WSAStartup(UINT16 wVersionRequested, LPWSADATA lpWSAData)
259 {
260   WSADATA WINSOCK_data = { 0x0101, 0x0101,
261                           "WINE Sockets 1.1",
262                         #ifdef linux
263                                 "Linux/i386",
264                         #elif defined(__NetBSD__)
265                                 "NetBSD/i386",
266                         #elif defined(sunos)
267                                 "SunOS",
268                         #elif defined(__FreeBSD__)
269                                 "FreeBSD",
270                         #elif defined(__OpenBSD__)
271                                 "OpenBSD/i386",
272                         #else
273                                 "Unknown",
274                         #endif
275                            WS_MAX_SOCKETS_PER_THREAD,
276                            WS_MAX_UDP_DATAGRAM, NULL };
277   HTASK16               tid = GetCurrentTask();
278   LPWSINFO              pwsi;
279
280   dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
281
282   if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
283       HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
284
285   if (!lpWSAData) return WSAEINVAL;
286
287   _ws_global_init();
288   if( _WSHeap == 0 ) return WSASYSNOTREADY;
289   
290   pwsi = wsi_find(GetCurrentTask());
291   if( pwsi == NULL )
292   {
293     if( (pwsi = (LPWSINFO)WS_ALLOC( sizeof(WSINFO))) )
294     {
295       int i = 0;
296       pwsi->tid = tid;
297       for( i = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++ )
298       { 
299         pwsi->sock[i].fd = -1; 
300         pwsi->sock[i].flags = i + 1; 
301       }
302       pwsi->sock[WS_MAX_SOCKETS_PER_THREAD - 1].flags = -1;
303     } 
304     else return WSASYSNOTREADY;
305     wsi_link(pwsi);
306   } else pwsi->num_startup++;
307
308   /* return winsock information */
309   memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
310
311   dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
312   return(0);
313 }
314
315 void WINSOCK_Shutdown()
316 {
317   if( async_qid != -1 )
318     if( msgctl(async_qid, IPC_RMID, NULL) == -1 )
319           fprintf(stderr,"failed to delete WS message queue.\n");
320     else async_qid = -1;
321 }
322
323 INT16 WSACleanup(void)
324 {
325   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
326
327   /* FIXME: do global cleanup if no current task */
328
329   dprintf_winsock(stddeb, "WSACleanup(%08x)\n", (unsigned)pwsi);
330   if( pwsi )
331   {
332       int       i, j, n;
333
334       if( pwsi->num_startup-- ) return 0;
335
336       SIGNAL_MaskAsyncEvents( TRUE );
337       WINSOCK_cancel_async_op(GetCurrentTask());
338       SIGNAL_MaskAsyncEvents( FALSE );
339
340       wsi_unlink(pwsi);
341       if( _wsi_list == NULL ) WINSOCK_Shutdown();
342
343       if( pwsi->flags & WSI_BLOCKINGCALL )
344           dprintf_winsock(stddeb,"\tinside blocking call!\n");
345       if( pwsi->num_async_rq )
346           dprintf_winsock(stddeb,"\thave %i outstanding async ops!\n", pwsi->num_async_rq );
347
348       for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++)
349         if( pwsi->sock[i].fd != -1 )
350         { 
351           n += cancel_async_select(&pwsi->sock[i]);
352           close(pwsi->sock[i].fd); j++; 
353         }
354       if( j ) 
355           dprintf_winsock(stddeb,"\tclosed %i sockets, killed %i async selects!\n", j, n);
356
357       if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer);
358       if( pwsi->dbuffer ) SEGPTR_FREE(pwsi->dbuffer);
359       WS_FREE(pwsi);
360       return 0;
361   }
362   return SOCKET_ERROR;
363 }
364
365 INT16 WSAGetLastError(void)
366 {
367   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
368   INT16         ret;
369
370   dprintf_winsock(stddeb, "WSAGetLastError(%08x)", (unsigned)pwsi);
371
372   ret = (pwsi) ? pwsi->err : WSANOTINITIALISED;
373
374   dprintf_winsock(stddeb, " = %i\n", (int)ret);
375   return ret;
376 }
377
378 void WSASetLastError(INT16 iError)
379 {
380   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
381
382   dprintf_winsock(stddeb, "WSASetLastError(%08x): %d\n", (unsigned)pwsi, (int)iError);
383
384   if( pwsi ) pwsi->err = iError;
385 }
386
387 int _check_ws(LPWSINFO pwsi, ws_socket* pws)
388 {
389   if( pwsi )
390     if( pwsi->flags & WSI_BLOCKINGCALL ) pwsi->err = WSAEINPROGRESS;
391     else if( WSI_CHECK_RANGE(pwsi, pws) ) return 1;
392     else pwsi->err = WSAENOTSOCK;
393   return 0;
394 }
395
396 int _check_buffer(LPWSINFO pwsi, int size)
397 {
398   if( pwsi->buffer && pwsi->buflen >= size ) return 1;
399   else SEGPTR_FREE(pwsi->buffer);
400   pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size)); 
401   return (pwsi->buffer != NULL);
402 }
403
404 /* ----- socket operations */
405
406 SOCKET16 WINSOCK_accept(SOCKET16 s, struct sockaddr *addr, INT16 *addrlen16)
407 {
408   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
409   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
410
411   dprintf_winsock(stddeb, "WS_ACCEPT(%08x): socket %04x\n", 
412                                    (unsigned)pwsi, (UINT16)s); 
413   if( _check_ws(pwsi, pws) )
414   {
415      int        sock, fd_flags, addrlen32 = *addrlen16;
416
417      /* this is how block info is supposed to be used -
418       * WSAIsBlocking() would then check WSI_BLOCKINGCALL bit.
419       */
420
421      fd_flags = fcntl(pws->fd, F_GETFL, 0);
422      if( !(fd_flags & O_NONBLOCK) ) pwsi->flags |= WSI_BLOCKINGCALL; 
423
424      if( (sock = accept(pws->fd, addr, &addrlen32)) >= 0 )
425      {
426         ws_socket*      pnew = wsi_alloc_socket(pwsi, sock); 
427         notify_client(pws, WS_FD_ACCEPT);
428         if( pnew )
429         {
430           if( pws->p_aop )
431               init_async_select(pnew, pws->p_aop->hWnd,
432                                       pws->p_aop->uMsg,
433                                       pws->p_aop->flags & ~WS_FD_ACCEPT );
434
435           pwsi->flags &= ~WSI_BLOCKINGCALL; 
436           return (SOCKET16)WS_PTR2HANDLE(pnew);
437         } 
438         else pwsi->err = WSAENOBUFS;
439      } 
440      else pwsi->err = wsaErrno();
441
442      pwsi->flags &= ~WSI_BLOCKINGCALL;
443   }
444   return INVALID_SOCKET;
445 }
446
447 INT16 WINSOCK_bind(SOCKET16 s, struct sockaddr *name, INT16 namelen)
448 {
449   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
450   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
451
452   dprintf_winsock(stddeb, "WS_BIND(%08x): socket %04x, ptr %8x, length %d\n", 
453                            (unsigned)pwsi, s, (int) name, namelen);
454 #if 0
455   dump_sockaddr(name);
456 #endif
457
458   if ( _check_ws(pwsi, pws) )
459     if (namelen >= sizeof(*name)) 
460        if ( ((struct sockaddr_in *)name)->sin_family == AF_INET )
461           if ( bind(pws->fd, name, namelen) < 0 ) 
462           {
463              int        loc_errno = errno;
464              dprintf_winsock(stddeb,"\tfailure - errno = %i\n", errno);
465              errno = loc_errno;
466              switch(errno)
467              {
468                 case EBADF: pwsi->err = WSAENOTSOCK; break;
469                 case EADDRNOTAVAIL: pwsi->err = WSAEINVAL; break;
470                 default: pwsi->err = wsaErrno();
471              }
472           }
473           else return 0;
474        else pwsi->err = WSAEAFNOSUPPORT;
475     else pwsi->err = WSAEFAULT;
476   return SOCKET_ERROR;
477 }
478
479 INT16 WINSOCK_closesocket(SOCKET16 s)
480 {
481   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
482   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
483
484   dprintf_winsock(stddeb, "WS_CLOSE(%08x): socket %08x\n", (unsigned)pwsi, s);
485
486   if( _check_ws(pwsi, pws) )
487   { 
488     int         fd = pws->fd;
489
490     cancel_async_select(pws);
491     pws->fd = -1;
492     pws->flags = (unsigned)pwsi->last_free;
493     pwsi->last_free = pws - &pwsi->sock[0];
494     if (close(fd) == 0) return 0;
495     pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
496   }
497   return SOCKET_ERROR;
498 }
499
500 INT16 WINSOCK_connect(SOCKET16 s, struct sockaddr *name, INT16 namelen)
501 {
502   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
503   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
504
505   dprintf_winsock(stddeb, "WS_CONNECT(%08x): socket %04x, ptr %8x, length %d\n", 
506                            (unsigned)pwsi, s, (int) name, namelen);
507 #if 0
508   dump_sockaddr(name);
509 #endif
510
511   if( _check_ws(pwsi, pws) )
512   {
513     if (connect(pws->fd, name, namelen) == 0) 
514     { 
515         if( pws->p_aop )
516             /* we need to notify handler process if
517              * connect() succeeded NOT in response to winsock message
518              */
519             notify_client(pws, WS_FD_CONNECTED);
520
521         pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT); 
522         return 0; 
523     }
524     pwsi->err = (errno == EINPROGRESS) ? WSAEWOULDBLOCK : wsaErrno();
525   }
526   return SOCKET_ERROR;
527 }
528
529 INT16 WINSOCK_getpeername(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
530 {
531   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
532   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
533
534   dprintf_winsock(stddeb, "WS_GETPEERNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
535                            (unsigned)pwsi, s, (int) name, *namelen);
536   if( _check_ws(pwsi, pws) )
537   {
538     int namelen32 = *namelen;
539     if (getpeername(pws->fd, name, &namelen32) == 0) 
540     { 
541 #if 0
542         dump_sockaddr(name);
543 #endif
544        *namelen = (INT16)namelen32; 
545         return 0; 
546     }
547     pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
548   }
549   return SOCKET_ERROR;
550 }
551
552 INT16 WINSOCK_getsockname(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
553 {
554   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
555   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
556
557   dprintf_winsock(stddeb, "WS_GETSOCKNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
558                           (unsigned)pwsi, s, (int) name, (int) *namelen);
559   if( _check_ws(pwsi, pws) )
560   {
561     int namelen32 = *namelen;
562     if (getsockname(pws->fd, name, &namelen32) == 0)
563     { 
564         *namelen = (INT16)namelen32; 
565          return 0; 
566     }
567     pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
568   }
569   return SOCKET_ERROR;
570 }
571
572 INT16 WINSOCK_getsockopt(SOCKET16 s, INT16 level, 
573                          INT16 optname, char *optval, INT16 *optlen)
574 {
575   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
576   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
577
578   dprintf_winsock(stddeb, "WS_GETSOCKOPT(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n", 
579                            (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
580
581   if( _check_ws(pwsi, pws) )
582   {
583      int        optlen32 = *optlen;
584
585      convert_sockopt(&level, &optname);
586      if (getsockopt(pws->fd, (int) level, optname, optval, &optlen32) == 0 )
587      { *optlen = (INT16)optlen32; return 0; }
588      pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
589   }
590   return SOCKET_ERROR;
591 }
592
593 u_long  WINSOCK_htonl(u_long hostlong)   { return( htonl(hostlong) ); }
594 u_short WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
595 u_long  WINSOCK_inet_addr(char *cp)      { return( inet_addr(cp) ); }
596 u_long  WINSOCK_ntohl(u_long netlong)    { return( ntohl(netlong) ); }
597 u_short WINSOCK_ntohs(u_short netshort)  { return( ntohs(netshort) ); }
598
599 SEGPTR WINSOCK_inet_ntoa(struct in_addr in)
600 {
601   /* use "buffer for dummies" here because some applications have 
602    * propensity to decode addresses in ws_hostent structure without 
603    * saving them first...
604    */
605
606   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
607
608   if( pwsi )
609   {
610     char*       s = inet_ntoa(in);
611     if( s ) 
612     {
613         if( pwsi->dbuffer == NULL )
614             if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(32)) == NULL )
615             {
616                 pwsi->err = WSAENOBUFS;
617                 return (SEGPTR)NULL;
618             }
619         strncpy(pwsi->dbuffer, s, 32 );
620         return SEGPTR_GET(pwsi->dbuffer); 
621     }
622     pwsi->err = wsaErrno();
623   }
624   return (SEGPTR)NULL;
625 }
626
627 INT16 WINSOCK_ioctlsocket(SOCKET16 s, UINT32 cmd, UINT32 *argp)
628 {
629   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
630   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
631
632   dprintf_winsock(stddeb, "WS_IOCTL(%08x): socket %04x, cmd %08x, ptr %8x\n", 
633                           (unsigned)pwsi, s, cmd, (unsigned) argp);
634   if( _check_ws(pwsi, pws) )
635   {
636     long        newcmd  = cmd;
637
638     switch( cmd )
639     {
640         case WS_FIONREAD:   
641                 newcmd=FIONREAD; 
642                 break;
643
644         case WS_FIONBIO:    
645                 newcmd=FIONBIO;  
646                 if( pws->p_aop && *argp == 0 ) 
647                 {
648                     pwsi->err = WSAEINVAL; 
649                     return SOCKET_ERROR; 
650                 }
651                 break;
652
653         case WS_SIOCATMARK: 
654                 newcmd=SIOCATMARK; 
655                 break;
656
657         case WS_IOW('f',125,u_long): 
658                 fprintf(stderr,"Warning: WS1.1 shouldn't be using async I/O\n");
659                 pwsi->err = WSAEINVAL; 
660                 return SOCKET_ERROR;
661
662         default:          
663                 /* Netscape tries hard to use bogus ioctl 0x667e */
664                 dprintf_winsock(stddeb,"\tunknown WS_IOCTL cmd (%08x)\n", cmd);
665     }
666     if( ioctl(pws->fd, newcmd, (char*)argp ) == 0 ) return 0;
667     pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno(); 
668   }
669   return SOCKET_ERROR;
670 }
671
672 INT16 WINSOCK_listen(SOCKET16 s, INT16 backlog)
673 {
674   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
675   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
676
677   dprintf_winsock(stddeb, "WS_LISTEN(%08x): socket %04x, backlog %d\n", 
678                           (unsigned)pwsi, s, backlog);
679   if( _check_ws(pwsi, pws) )
680   {
681     if( !pws->p_aop )
682     {
683       int  fd_flags = fcntl(pws->fd, F_GETFL, 0);
684       if( !(fd_flags & O_NONBLOCK) ) pws->flags |= WS_FD_ACCEPT;
685     }
686     else notify_client(pws, WS_FD_ACCEPT);
687
688     if (listen(pws->fd, backlog) == 0) return 0;
689     pwsi->err = wsaErrno();
690   }
691   return SOCKET_ERROR;
692 }
693
694 INT16 WINSOCK_recv(SOCKET16 s, char *buf, INT16 len, INT16 flags)
695 {
696   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
697   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
698
699   dprintf_winsock(stddeb, "WS_RECV(%08x): socket %04x, buf %8x, len %d, flags %d",
700                           (unsigned)pwsi, s, (unsigned)buf, len, flags);
701   if( _check_ws(pwsi, pws) )
702   {
703     int length;
704     if ((length = recv(pws->fd, buf, len, flags)) >= 0) 
705     { 
706         dprintf_winsock(stddeb, " -> %i bytes\n", length);
707         notify_client(pws, WS_FD_READ);
708         return (INT16)length;
709     }
710     pwsi->err = wsaErrno();
711   }
712   dprintf_winsock(stddeb, " -> ERROR\n");
713   return SOCKET_ERROR;
714 }
715
716 INT16 WINSOCK_recvfrom(SOCKET16 s, char *buf, INT16 len, INT16 flags, 
717                 struct sockaddr *from, INT16 *fromlen16)
718 {
719   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
720   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
721
722   dprintf_winsock(stddeb, "WS_RECVFROM(%08x): socket %04x, ptr %08x, len %d, flags %d\n",
723                           (unsigned)pwsi, s, (unsigned)buf, len, flags);
724   if( _check_ws(pwsi, pws) )
725   {
726     int length, fromlen32 = *fromlen16;
727
728     if ((length = recvfrom(pws->fd, buf, len, flags, from, &fromlen32)) >= 0)
729     {   
730       *fromlen16 = fromlen32; 
731        notify_client(pws, WS_FD_READ);
732        return (INT16)length;
733     }
734     pwsi->err = wsaErrno();
735   }
736   return SOCKET_ERROR;
737 }
738
739 INT16 WINSOCK_select(INT16 nfds, ws_fd_set *ws_readfds,
740                                  ws_fd_set *ws_writefds,
741                                  ws_fd_set *ws_exceptfds, struct timeval *timeout)
742 {
743   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
744         
745   dprintf_winsock(stddeb, "WS_SELECT(%08x): nfds %d (ignored), read %8x, write %8x, excp %8x\n", 
746           (unsigned) pwsi, nfds, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
747
748   if( pwsi )
749   {
750      int         highfd = 0;
751      fd_set      readfds, writefds, exceptfds, errorfds;
752
753      fd_set_normalize(&readfds, pwsi, ws_readfds, &highfd);
754      fd_set_normalize(&writefds, pwsi, ws_writefds, &highfd);
755      fd_set_normalize(&exceptfds, pwsi, ws_exceptfds, &highfd);
756      FD_ZERO(&errorfds);
757
758      if( (highfd = select(highfd + 1, &readfds, &writefds, &exceptfds, timeout)) >= 0 )
759      {
760           if( highfd )
761           {
762             fd_set_update(pwsi, &readfds, ws_readfds, &errorfds);
763             fd_set_update(pwsi, &writefds, ws_writefds, &errorfds);
764             fd_set_update_except(pwsi, &exceptfds, ws_exceptfds, &errorfds);
765           }
766           return highfd; 
767      }
768      pwsi->err = wsaErrno();
769   } 
770   return SOCKET_ERROR;
771 }
772
773 INT16 WINSOCK_send(SOCKET16 s, char *buf, INT16 len, INT16 flags)
774 {
775   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
776   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
777
778   dprintf_winsock(stddeb, "WS_SEND(%08x): socket %04x, ptr %08x, length %d, flags %d\n", 
779                           (unsigned)pwsi, s, (unsigned) buf, len, flags);
780   if( _check_ws(pwsi, pws) )
781   {
782     int         length;
783     if ((length = send(pws->fd, buf, len, flags)) < 0 ) 
784     {  
785         length = SOCKET_ERROR;
786         pwsi->err = wsaErrno();
787     }
788     notify_client(pws, WS_FD_WRITE);
789     return (INT16)length;
790   }
791   return SOCKET_ERROR;
792 }
793
794 INT16 WINSOCK_sendto(SOCKET16 s, char *buf, INT16 len, INT16 flags,
795                      struct sockaddr *to, INT16 tolen)
796 {
797   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
798   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
799
800   dprintf_winsock(stddeb, "WS_SENDTO(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
801                           (unsigned)pwsi, s, (unsigned) buf, len, flags);
802   if( _check_ws(pwsi, pws) )
803   {
804     int         length;
805
806     if ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 )
807     {
808         length = SOCKET_ERROR;
809         pwsi->err = wsaErrno();
810     }
811     notify_client(pws, WS_FD_WRITE);
812     return (INT16)length;
813   }
814   return SOCKET_ERROR;
815 }
816
817 INT16 WINSOCK_setsockopt(SOCKET16 s, INT16 level, INT16 optname, 
818                          char *optval, INT16 optlen)
819 {
820   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
821   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
822
823   dprintf_winsock(stddeb, "WS_SETSOCKOPT(%08x): socket %04x, level %d, opt %d, ptr %08x, len %d\n",
824                           (unsigned)pwsi, s, level, optname, (int) optval, optlen);
825   if( _check_ws(pwsi, pws) )
826   {
827     int         linger32[2];
828     convert_sockopt(&level, &optname);
829     if( optname == SO_LINGER )
830     {
831         INT16*     ptr = (INT16*)optval;
832         linger32[0] = ptr[0];
833         linger32[1] = ptr[1]; 
834         optval = (char*)&linger32;
835         optlen = sizeof(linger32);
836     }
837     if (setsockopt(pws->fd, level, optname, optval, optlen) == 0) return 0;
838     pwsi->err = wsaErrno();
839   }
840   return SOCKET_ERROR;
841 }
842
843 INT16 WINSOCK_shutdown(SOCKET16 s, INT16 how)
844 {
845   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
846   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
847
848   dprintf_winsock(stddeb, "WS_SHUTDOWN(%08x): socket %04x, how %i\n",
849                            (unsigned)pwsi, s, how );
850   if( _check_ws(pwsi, pws) )
851   {
852     pws->flags |= WS_FD_INACTIVE;
853     cancel_async_select(pws);
854
855     if (shutdown(pws->fd, how) == 0) return 0;
856     pwsi->err = wsaErrno();
857   }
858   return SOCKET_ERROR;
859 }
860
861 SOCKET16 WINSOCK_socket(INT16 af, INT16 type, INT16 protocol)
862 {
863   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
864
865   dprintf_winsock(stddeb, "WS_SOCKET(%08x): af=%d type=%d protocol=%d\n", 
866                           (unsigned)pwsi, af, type, protocol);
867
868   if( pwsi )
869   {
870     int         sock;
871
872     /* check the socket family */
873     switch(af) 
874     {
875         case AF_INET:
876         case AF_UNSPEC: break;
877         default:        pwsi->err = WSAEAFNOSUPPORT; return INVALID_SOCKET;
878     }
879
880     /* check the socket type */
881     switch(type) 
882     {
883         case SOCK_STREAM:
884         case SOCK_DGRAM:
885         case SOCK_RAW: break;
886         default:       pwsi->err = WSAESOCKTNOSUPPORT; return INVALID_SOCKET;
887     }
888
889     /* check the protocol type */
890     if ( protocol < 0 )  /* don't support negative values */
891     { pwsi->err = WSAEPROTONOSUPPORT; return INVALID_SOCKET; }
892
893     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
894         switch(protocol) 
895         {
896           case IPPROTO_TCP:
897              if (type == SOCK_STREAM) { af = AF_INET; break; }
898           case IPPROTO_UDP:
899              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
900           default: pwsi->err = WSAEPROTOTYPE; return INVALID_SOCKET;
901         }
902
903     if ((sock = socket(af, type, protocol)) >= 0) 
904     {
905         ws_socket*      pnew = wsi_alloc_socket(pwsi, sock);
906
907         dprintf_winsock(stddeb,"\tcreated %04x (handle %i)\n", sock, (UINT16)WS_PTR2HANDLE(pnew));
908
909         if( pnew ) return (SOCKET16)WS_PTR2HANDLE(pnew);
910         {
911           close(sock);
912           pwsi->err = WSAENOBUFS;
913           return INVALID_SOCKET;
914         }
915     }
916
917     if (errno == EPERM) /* raw socket denied */
918     {
919         fprintf(stderr, "WS_SOCKET: not enough privileges\n");
920         pwsi->err = WSAESOCKTNOSUPPORT;
921     } else pwsi->err = wsaErrno();
922   }
923  
924   dprintf_winsock(stddeb, "\t\tfailed!\n");
925   return INVALID_SOCKET;
926 }
927     
928
929 /* ----- database functions 
930  *
931  * Note that ws_...ent structures we return have SEGPTR pointers inside them.
932  */
933
934 static char*    NULL_STRING = "NULL";
935
936 /*
937 struct WIN_hostent *
938 */
939 SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT16 len, INT16 type)
940 {
941   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
942
943   dprintf_winsock(stddeb, "WS_GetHostByAddr(%08x): ptr %8x, len %d, type %d\n", 
944                           (unsigned)pwsi, (unsigned) addr, len, type);
945   if( pwsi )
946   {
947     struct hostent*     host;
948     if( (host = gethostbyaddr(addr, len, type)) != NULL )
949       if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
950           return SEGPTR_GET(pwsi->buffer);
951       else pwsi->err = WSAENOBUFS;
952     else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
953   } 
954   return NULL;
955 }
956
957 /*
958 struct WIN_hostent *
959 */
960 SEGPTR WINSOCK_gethostbyname(const char *name)
961 {
962   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
963
964   dprintf_winsock(stddeb, "WS_GetHostByName(%08x): %s\n",
965                           (unsigned)pwsi, (name)?name:"NULL");
966   if( pwsi )
967   {
968     struct hostent*     host;
969     if( (host = gethostbyname(name)) != NULL )
970       if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
971           return SEGPTR_GET(pwsi->buffer);
972       else pwsi->err = WSAENOBUFS;
973     else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
974   }
975   return NULL;
976 }
977
978 INT16 WINSOCK_gethostname(char *name, INT16 namelen)
979 {
980   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
981
982   dprintf_winsock(stddeb, "WS_GetHostName(%08x): name %s, len %d\n", 
983                           (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
984   if( pwsi )
985   {
986     if (gethostname(name, namelen) == 0) return 0;
987     pwsi->err = (errno == EINVAL) ? WSAEFAULT : wsaErrno();
988   }
989   return SOCKET_ERROR;
990 }
991
992 /*
993 struct WIN_protoent *
994 */
995 SEGPTR WINSOCK_getprotobyname(char *name)
996 {
997   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
998
999   dprintf_winsock(stddeb, "WS_GetProtoByName(%08x): %s\n",
1000                           (unsigned)pwsi, (name)?name:NULL_STRING);
1001   if( pwsi )
1002   {
1003     struct protoent*     proto;
1004     if( (proto = getprotobyname(name)) != NULL )
1005       if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
1006           return SEGPTR_GET(pwsi->buffer);
1007       else pwsi->err = WSAENOBUFS;
1008     else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1009   }
1010   return NULL;
1011 }
1012
1013 /*
1014 struct WIN_protoent *
1015 */
1016 SEGPTR WINSOCK_getprotobynumber(INT16 number)
1017 {
1018   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1019
1020   dprintf_winsock(stddeb, "WS_GetProtoByNumber(%08x): %i\n", (unsigned)pwsi, number);
1021
1022   if( pwsi )
1023   {
1024     struct protoent*     proto;
1025     if( (proto = getprotobynumber(number)) != NULL )
1026       if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
1027           return SEGPTR_GET(pwsi->buffer);
1028       else pwsi->err = WSAENOBUFS;
1029     else pwsi->err = WSANO_DATA;
1030   }
1031   return NULL;
1032 }
1033
1034 /*
1035 struct WIN_servent *
1036 */
1037 SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
1038 {
1039   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1040
1041   dprintf_winsock(stddeb, "WS_GetServByName(%08x): '%s', '%s'\n", 
1042                           (unsigned)pwsi, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
1043
1044   if( pwsi )
1045   {
1046     struct servent*     serv;
1047     if( (serv = getservbyname(name, proto)) != NULL )
1048       if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
1049           return SEGPTR_GET(pwsi->buffer);
1050       else pwsi->err = WSAENOBUFS;
1051     else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1052   }
1053   return NULL;
1054 }
1055
1056 /*
1057 struct WIN_servent *
1058 */
1059 SEGPTR WINSOCK_getservbyport(INT16 port, const char *proto)
1060 {
1061   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1062
1063   dprintf_winsock(stddeb, "WS_GetServByPort(%08x): %i, '%s'\n",
1064                           (unsigned)pwsi, (int)port, (proto)?proto:NULL_STRING);
1065   if( pwsi )
1066   {
1067     struct servent*     serv;
1068     if( (serv = getservbyport(port, proto)) != NULL )
1069       if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
1070           return SEGPTR_GET(pwsi->buffer);
1071       else pwsi->err = WSAENOBUFS;
1072     else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
1073   }
1074   return NULL;
1075 }
1076
1077
1078 /* ----------------------------------- Windows sockets extensions -- *
1079  *                                                                   *
1080  * ----------------------------------------------------------------- */
1081
1082 static int aop_control(ws_async_op* p_aop, int flag )
1083 {
1084   unsigned      lLength;
1085
1086   read(p_aop->fd[0], &lLength, sizeof(unsigned));
1087   if( LOWORD(lLength) )
1088     if( (int)LOWORD(lLength) <= p_aop->buflen )
1089     {
1090       char* buffer = (char*)PTR_SEG_TO_LIN(p_aop->buffer_base);
1091       read(p_aop->fd[0], buffer, LOWORD(lLength));
1092       switch( p_aop->flags )
1093       {
1094         case WSMSG_ASYNC_HOSTBYNAME:
1095         case WSMSG_ASYNC_HOSTBYADDR: 
1096              fixup_wshe((struct ws_hostent*)buffer, p_aop->buffer_base); break;
1097         case WSMSG_ASYNC_PROTOBYNAME:
1098         case WSMSG_ASYNC_PROTOBYNUM:
1099              fixup_wspe((struct ws_protoent*)buffer, p_aop->buffer_base); break;
1100         case WSMSG_ASYNC_SERVBYNAME:
1101         case WSMSG_ASYNC_SERVBYPORT:
1102              fixup_wsse((struct ws_servent*)buffer, p_aop->buffer_base); break;
1103         default:
1104              if( p_aop->flags ) fprintf(stderr,"Received unknown async request!\n"); 
1105              return AOP_CONTROL_REMOVE;
1106       }
1107     }
1108     else lLength =  ((UINT32)LOWORD(lLength)) | ((unsigned)WSAENOBUFS << 16);
1109
1110 #if 0
1111   printf("async op completed: hWnd [%04x], uMsg [%04x], aop [%04x], event [%08x]\n",
1112          p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
1113 #endif
1114
1115   PostMessage16(p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
1116   return AOP_CONTROL_REMOVE;
1117 }
1118
1119
1120 static HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, LPCSTR init,
1121                                  INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen, UINT32 flag)
1122 {
1123   /* queue 'flag' request and fork off its handler */
1124
1125   async_ctl.ws_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op));
1126
1127   if( async_ctl.ws_aop )
1128   {
1129       HANDLE16        handle = (HANDLE16)WS_PTR2HANDLE(async_ctl.ws_aop);
1130
1131       if( pipe(async_ctl.ws_aop->fd) == 0 )
1132       {
1133         async_ctl.init = (char*)init;
1134         async_ctl.lLength = len;
1135         async_ctl.lEvent = type;
1136
1137         async_ctl.ws_aop->hWnd = hWnd;
1138         async_ctl.ws_aop->uMsg = uMsg;
1139
1140         async_ctl.ws_aop->buffer_base = sbuf; async_ctl.ws_aop->buflen = buflen;
1141         async_ctl.ws_aop->flags = flag;
1142         async_ctl.ws_aop->aop_control = &aop_control;
1143         WINSOCK_link_async_op( async_ctl.ws_aop );
1144
1145         async_ctl.ws_aop->pid = fork();
1146         if( async_ctl.ws_aop->pid )
1147         {
1148             close(async_ctl.ws_aop->fd[1]);        /* write endpoint */
1149
1150            /* Damn, BSD'ish SIGIO doesn't work on pipes/streams
1151             *
1152             * async_io(async_ctl.ws_aop->fd[0], 1);
1153             */
1154
1155             dprintf_winsock(stddeb, "\tasync_op = %04x (child %i)\n",
1156                                     handle, async_ctl.ws_aop->pid);
1157             return handle;
1158         } else
1159                 /* child process */
1160                  {
1161                    close(async_ctl.ws_aop->fd[0]); /* read endpoint */
1162                    switch(flag)
1163                    {
1164                      case WSMSG_ASYNC_HOSTBYADDR:
1165                      case WSMSG_ASYNC_HOSTBYNAME:
1166                         WS_do_async_gethost(pwsi,flag);
1167                      case WSMSG_ASYNC_PROTOBYNUM:
1168                      case WSMSG_ASYNC_PROTOBYNAME:
1169                         WS_do_async_getproto(pwsi,flag);
1170                      case WSMSG_ASYNC_SERVBYPORT:
1171                      case WSMSG_ASYNC_SERVBYNAME:
1172                         WS_do_async_getserv(pwsi,flag);
1173                    }
1174                    _exit(0); /* skip atexit()'ed cleanup */
1175                  }
1176       }
1177       WS_FREE(async_ctl.ws_aop);
1178       pwsi->err = wsaErrno();
1179   } else pwsi->err = WSAEWOULDBLOCK;
1180   return 0;
1181 }
1182
1183 HANDLE16 WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
1184                                INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen)
1185 {
1186   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1187
1188   dprintf_winsock(stddeb, "WS_AsyncGetHostByAddr(%08x): hwnd %04x, msg %04x, addr %08x[%i]\n",
1189                           (unsigned)pwsi, hWnd, uMsg, (unsigned)addr , len );
1190
1191   if( pwsi ) 
1192     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, addr, len,
1193                             type, sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR );
1194   return 0;
1195 }
1196
1197
1198 HANDLE16 WSAAsyncGetHostByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
1199                                SEGPTR sbuf, INT16 buflen)
1200 {
1201   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1202
1203   dprintf_winsock(stddeb, "WS_AsyncGetHostByName(%08x): hwnd %04x, msg %04x, host %s, buffer %i\n",
1204                           (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen );
1205
1206   if( pwsi )
1207     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
1208                             0, sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME );
1209   return 0;
1210 }                     
1211
1212
1213 HANDLE16 WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
1214                                 SEGPTR sbuf, INT16 buflen)
1215 {
1216   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1217
1218   dprintf_winsock(stddeb, "WS_AsyncGetProtoByName(%08x): hwnd %04x, msg %04x, protocol %s\n",
1219                           (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING );
1220
1221   if( pwsi )
1222     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
1223                             0, sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME );
1224   return 0;
1225 }
1226
1227
1228 HANDLE16 WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 uMsg, INT16 number, 
1229                                   SEGPTR sbuf, INT16 buflen)
1230 {
1231   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1232
1233   dprintf_winsock(stddeb, "WS_AsyncGetProtoByNumber(%08x): hwnd %04x, msg %04x, num %i\n",
1234                           (unsigned)pwsi, hWnd, uMsg, number );
1235
1236   if( pwsi )
1237     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, NULL, 0,
1238                             number, sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM );
1239   return 0;
1240 }
1241
1242
1243 HANDLE16 WSAAsyncGetServByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
1244                                LPCSTR proto, SEGPTR sbuf, INT16 buflen)
1245 {
1246   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1247
1248   dprintf_winsock(stddeb, "WS_AsyncGetServByName(%08x): hwnd %04x, msg %04x, name %s, proto %s\n",
1249                    (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING );
1250
1251   if( pwsi )
1252   { 
1253     async_ctl.buffer = (char*)proto;
1254     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
1255                             0, sbuf, buflen, WSMSG_ASYNC_SERVBYNAME );
1256   }
1257   return 0;
1258 }
1259
1260
1261 HANDLE16 WSAAsyncGetServByPort(HWND16 hWnd, UINT16 uMsg, INT16 port, 
1262                                LPCSTR proto, SEGPTR sbuf, INT16 buflen)
1263 {
1264   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1265
1266   dprintf_winsock(stddeb, "WS_AsyncGetServByPort(%08x): hwnd %04x, msg %04x, port %i, proto %s\n",
1267                            (unsigned)pwsi, hWnd, uMsg, port, (proto)?proto:NULL_STRING );
1268
1269   if( pwsi )
1270     return __WSAsyncDBQuery(pwsi, hWnd, uMsg, proto, 0,
1271                             port, sbuf, buflen, WSMSG_ASYNC_SERVBYPORT );
1272   return 0;
1273 }
1274
1275 INT16 WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
1276 {
1277   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1278   ws_async_op*          p_aop = (ws_async_op*)WS_HANDLE2PTR(hAsyncTaskHandle);
1279
1280   dprintf_winsock(stddeb, "WS_CancelAsyncRequest(%08x): handle %04x\n", 
1281                            (unsigned)pwsi, hAsyncTaskHandle);
1282   if( pwsi )
1283     if( WINSOCK_check_async_op(p_aop) )
1284     {
1285         kill(p_aop->pid, SIGKILL); 
1286         waitpid(p_aop->pid, NULL, 0); /* just in case */
1287         close(p_aop->fd[0]);
1288         WINSOCK_unlink_async_op(p_aop);
1289         WS_FREE(p_aop);
1290         return 0;
1291     }
1292     else pwsi->err = WSAEINVAL;
1293   return SOCKET_ERROR;
1294 }
1295
1296 /* ----- asynchronous select() */
1297
1298 int cancel_async_select(ws_socket* pws)
1299 {
1300   if( pws->p_aop )
1301   {
1302     kill(pws->p_aop->pid, SIGKILL);
1303     waitpid(pws->p_aop->pid, NULL, 0);
1304     WS_FREE(pws->p_aop); 
1305     pws->p_aop = NULL;
1306     return 1;
1307   }
1308   return 0;
1309 }
1310
1311 void _sigusr1_handler_parent(int sig)
1312 {
1313   /* child process puts MTYPE_CLIENT data packet into the
1314    * 'async_qid' message queue and signals us with SIGUSR1.
1315    * This handler reads the queue and posts 'uMsg' notification
1316    * message.
1317    */
1318
1319   ipc_packet            ipack;
1320
1321   signal( SIGUSR1, _sigusr1_handler_parent);
1322   while( msgrcv(async_qid, (struct msgbuf*)&ipack,
1323           MTYPE_CLIENT_SIZE, MTYPE_CLIENT, IPC_NOWAIT) != -1 )
1324   {
1325     if( ipack.wParam && abs((short)ipack.wParam) < 32768 )
1326     {
1327       ws_socket*        pws = (ws_socket*)WS_HANDLE2PTR(ipack.wParam);
1328       if( pws->p_aop && abs((char*)_ws_stub - (char*)pws->p_aop) < 32768 )
1329       {
1330           pws->flags &= ~(ipack.lParam);
1331 #if 0
1332           printf("async event - hWnd %04x, uMsg %04x [%08x]\n",
1333                   pws->p_aop->hWnd, pws->p_aop->uMsg, ipack.lParam );
1334 #endif
1335           PostMessage16(pws->p_aop->hWnd, pws->p_aop->uMsg, 
1336                         (WPARAM16)ipack.wParam, (LPARAM)ipack.lParam );
1337       }
1338       else fprintf(stderr,"AsyncSelect:stray async_op in socket %04x!\n", ipack.wParam);
1339     }
1340     else fprintf(stderr,"AsyncSelect:stray socket at %04x!\n", ipack.wParam);
1341   }
1342 }
1343
1344 int notify_client( ws_socket* pws, unsigned flag )
1345 {
1346   if( pws->p_aop && ((pws->p_aop->flags & flag) ||
1347                      (flag == WS_FD_CONNECTED && pws->flags & WS_FD_CONNECT)) )
1348   {
1349      async_ctl.ip.mtype = MTYPE_PARENT;
1350      async_ctl.ip.lParam = flag;
1351      while( msgsnd(async_qid, (struct msgbuf*)&(async_ctl.ip),
1352                                MTYPE_PARENT_SIZE, 0) == -1 )
1353      { 
1354         if( errno == EINTR ) continue;
1355         else
1356         {
1357             perror("AsyncSelect(parent)"); 
1358             cancel_async_select(pws);
1359             pws->flags &= WS_FD_INTERNAL;
1360             return 0;
1361         }
1362      }
1363      kill(pws->p_aop->pid, SIGUSR1);
1364      return 1;
1365   }
1366   return 0;
1367 }
1368
1369 INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
1370 {
1371     ws_async_op*        p_aop;
1372
1373     if( cancel_async_select(pws) )  /* delete old async handler if any */
1374       pws->flags &= WS_FD_INTERNAL;
1375
1376     if( lEvent == 0 ) return 0;
1377
1378     /* setup async handler - some data may be redundant */
1379
1380     WINSOCK_unblock_io(pws->fd, 1);
1381     if( (p_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op))) )
1382     {
1383       p_aop->hWnd = hWnd;
1384       p_aop->uMsg = uMsg;
1385       pws->p_aop = p_aop;
1386
1387       async_ctl.lEvent = p_aop->flags = lEvent;
1388       async_ctl.ws_sock = pws;
1389       async_ctl.ip.wParam = (UINT16)WS_PTR2HANDLE(pws);
1390       async_ctl.ip.lParam = 0;
1391
1392       p_aop->pid = fork();
1393       if( p_aop->pid != -1 )
1394         if( p_aop->pid == 0 ) WINSOCK_do_async_select(); /* child process */
1395         else pws->flags |= lEvent;
1396
1397       signal( SIGUSR1, _sigusr1_handler_parent );
1398       return 0;                                  /* Wine process */
1399     }
1400     return SOCKET_ERROR;
1401 }
1402
1403 INT16 WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
1404 {
1405   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
1406   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
1407
1408   dprintf_winsock(stddeb, "WS_AsyncSelect(%08x): %04x, hWnd %04x, uMsg %04x, event %08x\n",
1409                           (unsigned)pwsi, s, hWnd, uMsg, (unsigned)lEvent );
1410   if( _check_ws(pwsi, pws) )
1411     if( init_async_select(pws, hWnd, uMsg, lEvent) == 0 ) return 0;
1412     else pwsi->err = WSAENOBUFS;
1413   return SOCKET_ERROR; 
1414 }
1415
1416 /* ----- miscellaneous */
1417
1418 INT16 __WSAFDIsSet(SOCKET16 fd, ws_fd_set *set)
1419 {
1420   int i = set->fd_count;
1421   
1422   dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set);
1423     
1424   while (i--)
1425       if (set->fd_array[i] == fd) return 1;
1426   return 0;
1427 }                                                            
1428
1429 BOOL16 WSAIsBlocking(void)
1430 {
1431   /* By default WinSock should set all its sockets to non-blocking mode
1432    * and poll in PeekMessage loop when processing "blocking" ones. This 
1433    * function * is supposed to tell if program is in this loop. Our 
1434    * blocking calls are truly blocking so we always return FALSE.
1435    *
1436    * Note: It is allowed to call this function without prior WSAStartup().
1437    */
1438
1439   dprintf_winsock(stddeb, "WS_IsBlocking()\n");
1440   return FALSE;
1441 }
1442
1443 INT16 WSACancelBlockingCall(void)
1444 {
1445   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1446
1447   dprintf_winsock(stddeb, "WS_CancelBlockingCall(%08x)\n", (unsigned)pwsi);
1448
1449   if( pwsi ) return 0;
1450   return SOCKET_ERROR;
1451 }
1452
1453 FARPROC16 WSASetBlockingHook16(FARPROC16 lpBlockFunc)
1454 {
1455   FARPROC16             prev;
1456   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1457
1458   dprintf_winsock(stddeb, "WS_SetBlockingHook16(%08x): hook %08x\n", 
1459                           (unsigned)pwsi, (unsigned) lpBlockFunc);
1460
1461   if( pwsi ) { 
1462       prev = pwsi->blocking_hook; 
1463       pwsi->blocking_hook = lpBlockFunc; 
1464       return prev; 
1465   }
1466   return 0;
1467 }
1468
1469 FARPROC32 WSASetBlockingHook32(FARPROC32 lpBlockFunc)
1470 {
1471   fprintf( stderr, "WSASetBlockingHook32(%p): empty stub\n", lpBlockFunc );
1472   return NULL;
1473 }
1474
1475 INT16 WSAUnhookBlockingHook16(void)
1476 {
1477   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
1478
1479   dprintf_winsock(stddeb, "WS_UnhookBlockingHook(%08x)\n", (unsigned)pwsi);
1480   if( pwsi ) return (INT16)(INT32)(pwsi->blocking_hook = (FARPROC16)NULL);
1481   return SOCKET_ERROR;
1482 }
1483
1484 INT32 WSAUnhookBlockingHook32(void)
1485 {
1486   fprintf( stderr, "WSAUnhookBlockingHook32(): empty stub\n");
1487   return NULL;
1488 }
1489
1490 VOID
1491 WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,LPDWORD x5,LPDWORD x6) 
1492 {
1493         fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n",
1494                 x1,x2,x3,x4,x5,x6
1495         );
1496         fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
1497                 x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0
1498         );
1499         return;
1500 }
1501 /* ----------------------------------- end of API stuff */
1502
1503
1504
1505 /* ----------------------------------- helper functions */
1506
1507 static int list_size(char** l, int item_size)
1508 {
1509   int i,j = 0;
1510   if(l)
1511   { for(i=0;l[i];i++) 
1512         j += (item_size) ? item_size : strlen(l[i]) + 1;
1513     j += (i + 1) * sizeof(char*); }
1514   return j;
1515 }
1516
1517 static int list_dup(char** l_src, char* ref, char* base, int item_size)
1518
1519    /* base is either either equal to ref or 0 or SEGPTR */
1520
1521    char*                p = ref;
1522    char**               l_to = (char**)ref;
1523    int                  i,j,k;
1524
1525    for(j=0;l_src[j];j++) ;
1526    p += (j + 1) * sizeof(char*);
1527    for(i=0;i<j;i++)
1528    { l_to[i] = base + (p - ref);
1529      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
1530      memcpy(p, l_src[i], k); p += k; }
1531    l_to[i] = NULL;
1532    return (p - ref);
1533 }
1534
1535 /* ----- hostent */
1536
1537 static int hostent_size(struct hostent* p_he)
1538 {
1539   int size = 0;
1540   if( p_he )
1541   { size  = sizeof(struct hostent); 
1542     size += strlen(p_he->h_name) + 1;
1543     size += list_size(p_he->h_aliases, 0);  
1544     size += list_size(p_he->h_addr_list, p_he->h_length ); }
1545   return size;
1546 }
1547
1548 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
1549 {
1550    /* Duplicate hostent structure and flatten data (with its pointers)
1551     * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or 
1552     * relative to 0 depending on "flag" value. Return data size (also 
1553     * in the pwsi->buflen).
1554     */
1555
1556    int size = hostent_size(p_he);
1557    if( size )
1558    {
1559      char*           p_name,*p_aliases,*p_addr,*p_base,*p;
1560
1561      _check_buffer(pwsi, size);
1562      p = pwsi->buffer;
1563      p_base = (flag & WS_DUP_OFFSET) ? NULL
1564                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
1565      p += (flag & WS_DUP_SEGPTR) ? sizeof(struct ws_hostent) : sizeof(struct hostent);
1566      p_name = p;
1567      strcpy(p, p_he->h_name); p += strlen(p) + 1;
1568      p_aliases = p;
1569      p += list_dup(p_he->h_aliases, p, p_base + (p - pwsi->buffer), 0);
1570      p_addr = p;
1571      list_dup(p_he->h_addr_list, p, p_base + (p - pwsi->buffer), p_he->h_length);
1572      if( !(flag & WS_DUP_SEGPTR) )
1573      { struct hostent* p_to = (struct hostent*)pwsi->buffer;
1574        p_to->h_addrtype = p_he->h_addrtype; p_to->h_length = p_he->h_length;
1575        p_to->h_name = p_base + (p_name - pwsi->buffer);
1576        p_to->h_aliases = (char**)(p_base + (p_aliases - pwsi->buffer));
1577        p_to->h_addr_list = (char**)(p_base + (p_addr - pwsi->buffer)); }
1578      else
1579      { struct ws_hostent* p_to = (struct ws_hostent*)pwsi->buffer;
1580        p_to->h_addrtype = (INT16)p_he->h_addrtype; 
1581        p_to->h_length = (INT16)p_he->h_length;
1582        p_to->h_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
1583        p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
1584        p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - pwsi->buffer));
1585
1586        return (size + sizeof(struct ws_hostent) - sizeof(struct hostent)); }
1587    }
1588    return size;
1589 }
1590
1591 void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base)
1592 {
1593    /* add 'base' to ws_hostent pointers to convert them from offsets */ 
1594
1595    int i;
1596    unsigned*    p_aliases,*p_addr;
1597
1598    p_aliases = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_aliases); 
1599    p_addr = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_addr_list);
1600    ((unsigned)(p_wshe->h_name)) += (unsigned)base;
1601    ((unsigned)(p_wshe->h_aliases)) += (unsigned)base;
1602    ((unsigned)(p_wshe->h_addr_list)) += (unsigned)base;
1603    for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
1604    for(i=0;p_addr[i];i++) p_addr[i] += (unsigned)base;
1605 }
1606
1607 /* ----- protoent */
1608
1609 static int protoent_size(struct protoent* p_pe)
1610 {
1611   int size = 0;
1612   if( p_pe )
1613   { size  = sizeof(struct protoent);
1614     size += strlen(p_pe->p_name) + 1;
1615     size += list_size(p_pe->p_aliases, 0); }
1616   return size;
1617 }
1618
1619 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
1620 {
1621    int size = protoent_size(p_pe);
1622    if( size )
1623    {
1624      char*            p_name,*p_aliases,*p_base,*p;
1625
1626      _check_buffer(pwsi, size);
1627      p = pwsi->buffer; 
1628      p_base = (flag & WS_DUP_OFFSET) ? NULL
1629                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
1630      p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_protoent) : sizeof(struct protoent);
1631      p_name = p;
1632      strcpy(p, p_pe->p_name); p += strlen(p) + 1;
1633      p_aliases = p;
1634      list_dup(p_pe->p_aliases, p, p_base + (p - pwsi->buffer), 0);
1635      if( !(flag & WS_DUP_NATIVE) )
1636      { struct protoent* p_to = (struct protoent*)pwsi->buffer;
1637        p_to->p_proto = p_pe->p_proto;
1638        p_to->p_name = p_base + (p_name - pwsi->buffer); 
1639        p_to->p_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
1640      else
1641      { struct ws_protoent* p_to = (struct ws_protoent*)pwsi->buffer;
1642        p_to->p_proto = (INT16)p_pe->p_proto;
1643        p_to->p_name = (SEGPTR)(p_base) + (p_name - pwsi->buffer);
1644        p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - pwsi->buffer)); 
1645        return (size + sizeof(struct ws_protoent) - sizeof(struct protoent)); }
1646    }
1647    return size;
1648 }
1649
1650 void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base)
1651 {
1652    int i;
1653    unsigned*       p_aliases = (unsigned*)((char*)p_wspe + (unsigned)p_wspe->p_aliases); 
1654    ((unsigned)(p_wspe->p_name)) += (unsigned)base;
1655    ((unsigned)(p_wspe->p_aliases)) += (unsigned)base;
1656    for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
1657 }
1658
1659 /* ----- servent */
1660
1661 static int servent_size(struct servent* p_se)
1662 {
1663   int size = 0;
1664   if( p_se )
1665   { size += sizeof(struct servent);
1666     size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
1667     size += list_size(p_se->s_aliases, 0); }
1668   return size;
1669 }
1670
1671 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
1672 {
1673    int size = servent_size(p_se);
1674    if( size )
1675    {
1676      char*           p_name,*p_aliases,*p_proto,*p_base,*p;
1677
1678      _check_buffer(pwsi, size);
1679      p = pwsi->buffer;
1680      p_base = (flag & WS_DUP_OFFSET) ? NULL 
1681                                      : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
1682      p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_servent) : sizeof(struct servent);
1683      p_name = p;
1684      strcpy(p, p_se->s_name); p += strlen(p) + 1;
1685      p_proto = p;
1686      strcpy(p, p_se->s_proto); p += strlen(p) + 1;
1687      p_aliases = p;
1688      list_dup(p_se->s_aliases, p, p_base + (p - pwsi->buffer), 0);
1689
1690      if( !(flag & WS_DUP_SEGPTR) )
1691      { struct servent* p_to = (struct servent*)pwsi->buffer;
1692        p_to->s_port = p_se->s_port;
1693        p_to->s_name = p_base + (p_name - pwsi->buffer); 
1694        p_to->s_proto = p_base + (p_proto - pwsi->buffer);
1695        p_to->s_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
1696      else
1697      { struct ws_servent* p_to = (struct ws_servent*)pwsi->buffer;
1698        p_to->s_port = (INT16)p_se->s_port;
1699        p_to->s_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
1700        p_to->s_proto = (SEGPTR)(p_base + (p_proto - pwsi->buffer));
1701        p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer)); 
1702        return (size + sizeof(struct ws_servent) - sizeof(struct servent)); }
1703    }
1704    return size;
1705 }
1706
1707 void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base)
1708 {
1709    int i;
1710    unsigned*       p_aliases = (unsigned*)((char*)p_wsse + (unsigned)p_wsse->s_aliases);
1711    ((unsigned)(p_wsse->s_name)) += (unsigned)base;
1712    ((p_wsse->s_proto)) += (unsigned)base;
1713    ((p_wsse->s_aliases)) += (unsigned)base;
1714    for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
1715 }
1716
1717 /* ----------------------------------- error handling */
1718
1719 UINT16 wsaErrno(void)
1720 {
1721     int loc_errno = errno; 
1722 #if defined(__FreeBSD__)
1723        dprintf_winsock(stderr, "winsock: errno %d, (%s).\n", 
1724                                          errno, sys_errlist[errno]);
1725 #else
1726        dprintf_winsock(stderr, "winsock: errno %d\n", errno);
1727 #endif
1728
1729     switch(loc_errno)
1730     {
1731         case EINTR:             return WSAEINTR;
1732         case EBADF:             return WSAEBADF;
1733         case EACCES:            return WSAEACCES;
1734         case EFAULT:            return WSAEFAULT;
1735         case EINVAL:            return WSAEINVAL;
1736         case EMFILE:            return WSAEMFILE;
1737         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
1738         case EINPROGRESS:       return WSAEINPROGRESS;
1739         case EALREADY:          return WSAEALREADY;
1740         case ENOTSOCK:          return WSAENOTSOCK;
1741         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
1742         case EMSGSIZE:          return WSAEMSGSIZE;
1743         case EPROTOTYPE:        return WSAEPROTOTYPE;
1744         case ENOPROTOOPT:       return WSAENOPROTOOPT;
1745         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
1746         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
1747         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
1748         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
1749         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
1750         case EADDRINUSE:        return WSAEADDRINUSE;
1751         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
1752         case ENETDOWN:          return WSAENETDOWN;
1753         case ENETUNREACH:       return WSAENETUNREACH;
1754         case ENETRESET:         return WSAENETRESET;
1755         case ECONNABORTED:      return WSAECONNABORTED;
1756         case ECONNRESET:        return WSAECONNRESET;
1757         case ENOBUFS:           return WSAENOBUFS;
1758         case EISCONN:           return WSAEISCONN;
1759         case ENOTCONN:          return WSAENOTCONN;
1760         case ESHUTDOWN:         return WSAESHUTDOWN;
1761         case ETOOMANYREFS:      return WSAETOOMANYREFS;
1762         case ETIMEDOUT:         return WSAETIMEDOUT;
1763         case ECONNREFUSED:      return WSAECONNREFUSED;
1764         case ELOOP:             return WSAELOOP;
1765         case ENAMETOOLONG:      return WSAENAMETOOLONG;
1766         case EHOSTDOWN:         return WSAEHOSTDOWN;
1767         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
1768         case ENOTEMPTY:         return WSAENOTEMPTY;
1769 #ifdef EPROCLIM
1770         case EPROCLIM:          return WSAEPROCLIM;
1771 #endif
1772 #ifdef EUSERS
1773         case EUSERS:            return WSAEUSERS;
1774 #endif
1775 #ifdef EDQUOT
1776         case EDQUOT:            return WSAEDQUOT;
1777 #endif
1778 #ifdef ESTALE
1779         case ESTALE:            return WSAESTALE;
1780 #endif
1781 #ifdef EREMOTE
1782         case EREMOTE:           return WSAEREMOTE;
1783 #endif
1784
1785        /* just in case we ever get here and there are no problems */
1786         case 0:                 return 0;
1787         default:
1788                 fprintf(stderr, "winsock: unknown errno %d!\n", errno);
1789                 return WSAEOPNOTSUPP;
1790     }
1791 }
1792
1793 UINT16 wsaHerrno(void)
1794 {
1795     int         loc_errno = h_errno;
1796
1797 #if defined(__FreeBSD__)
1798     dprintf_winsock(stderr, "winsock: h_errno %d, (%s).\n", 
1799                     h_errno, sys_errlist[h_errno]);
1800 #else
1801     dprintf_winsock(stderr, "winsock: h_errno %d.\n", h_errno);
1802 #ifndef sun
1803     if( debugging_winsock )  herror("wine: winsock: wsaherrno");
1804 #endif
1805 #endif
1806
1807     switch(loc_errno)
1808     {
1809         case HOST_NOT_FOUND:    return WSAHOST_NOT_FOUND;
1810         case TRY_AGAIN:         return WSATRY_AGAIN;
1811         case NO_RECOVERY:       return WSANO_RECOVERY;
1812         case NO_DATA:           return WSANO_DATA; 
1813
1814         case 0:                 return 0;
1815         default:
1816                 fprintf(stderr, "winsock: unknown h_errno %d!\n", h_errno);
1817                 return WSAEOPNOTSUPP;
1818     }
1819 }
1820
1821