Release 950727
[wine] / misc / winsocket.c
1 /*
2  * based on Windows Sockets 1.1 specs
3  * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4  * 
5  * (C) 1993,1994 John Brezak, Erik Bos.
6  */
7  
8 #include <stdio.h>
9 #include <string.h>
10 #include <signal.h>
11 #include <sys/types.h>
12 #include <sys/ipc.h>
13 #include <sys/ioctl.h>
14 #include <sys/msg.h>
15 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <fcntl.h>
19 #include <errno.h>
20 #include <netdb.h>
21 #include <unistd.h>
22 #include "winsock.h"
23 #include "toolhelp.h"
24 #include "stddebug.h"
25 #include "debug.h"
26
27 static WORD wsa_errno;
28 static int wsa_initted;
29 static key_t wine_key = 0;
30 static FARPROC BlockFunction;
31 static fd_set fd_in_use;
32
33 struct ipc_packet {
34         long    mtype;
35         HANDLE  handle;
36         HWND    hWnd;
37         WORD    wMsg;
38         LONG    lParam;
39 };
40
41 #ifndef WINELIB
42 #pragma pack(1)
43 #endif
44
45 #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long))
46 #define MTYPE 0xb0b0eb05
47
48 /* These structures are Win16 only */
49
50 struct WIN_hostent  {
51         SEGPTR  h_name WINE_PACKED;             /* official name of host */
52         SEGPTR  h_aliases WINE_PACKED;  /* alias list */
53         INT     h_addrtype WINE_PACKED;         /* host address type */
54         INT     h_length WINE_PACKED;           /* length of address */
55         char    **h_addr_list WINE_PACKED;      /* list of addresses from name server */
56         char    *names[2];
57         char    hostname[200];
58 };
59
60 struct  WIN_protoent {
61         SEGPTR  p_name WINE_PACKED;             /* official protocol name */
62         SEGPTR  p_aliases WINE_PACKED;  /* alias list */
63         INT     p_proto WINE_PACKED;            /* protocol # */
64 };
65
66 struct  WIN_servent {
67         SEGPTR  s_name WINE_PACKED;             /* official service name */
68         SEGPTR  s_aliases WINE_PACKED;  /* alias list */
69         INT     s_port WINE_PACKED;             /* port # */
70         SEGPTR  s_proto WINE_PACKED;            /* protocol to use */
71 };
72
73 struct WinSockHeap {
74         char    ntoa_buffer[32];
75
76         struct  WIN_hostent hostent_addr;
77         struct  WIN_hostent hostent_name;
78         struct  WIN_protoent protoent_name;
79         struct  WIN_protoent protoent_number;
80         struct  WIN_servent servent_name;
81         struct  WIN_servent servent_port;
82
83         struct  WIN_hostent WSAhostent_addr;
84         struct  WIN_hostent WSAhostent_name;
85         struct  WIN_protoent WSAprotoent_name;
86         struct  WIN_protoent WSAprotoent_number;        
87         struct  WIN_servent WSAservent_name;
88         struct  WIN_servent WSAservent_port;
89         /* 8K scratch buffer for aliases and friends are hopefully enough */
90         char scratch[8192];
91 };
92 static struct WinSockHeap *Heap;
93 static int HeapHandle;
94 static int ScratchPtr;
95
96 #ifndef WINELIB
97 #define GET_SEG_PTR(x)  MAKELONG((int)((char*)(x)-(char*)Heap), \
98                                                         GlobalHandleToSel(HeapHandle))
99 #else
100 #define GET_SEG_PTR(x)  (x)
101 #endif
102
103 #ifndef WINELIB
104 #pragma pack(4)
105 #endif
106
107 #define dump_sockaddr(a) \
108         fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
109                         ((struct sockaddr_in *)a)->sin_family, \
110                         inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
111                         ntohs(((struct sockaddr_in *)a)->sin_port))
112
113 static void ResetScratch()
114 {
115         ScratchPtr=0;
116 }
117
118 static void *scratch_alloc(int size)
119 {
120         char *ret;
121         if(ScratchPtr+size > sizeof(Heap->scratch))
122                 return 0;
123         ret = Heap->scratch + ScratchPtr;
124         ScratchPtr += size;
125         return ret;
126 }
127
128 static SEGPTR scratch_strdup(char * s)
129 {
130         char *ret=scratch_alloc(strlen(s)+1);
131         strcpy(ret,s);
132         return GET_SEG_PTR(ret);
133 }
134
135 static WORD wsaerrno(void)
136 {
137 #ifdef DEBUG_WINSOCK
138 #ifndef sun
139 #if defined(__FreeBSD__)
140                 fprintf(stderr, "winsock: errno %d, (%s).\n", 
141                                         errno, sys_errlist[errno]);
142 #else
143                 fprintf(stderr, "winsock: errno %d, (%s).\n", 
144                                         errno, strerror(errno));
145 #endif
146 #else
147                 fprintf(stderr, "winsock: errno %d\n", errno);
148 #endif
149 #endif
150
151         switch(errno)
152         {
153         case EINTR:             return WSAEINTR;
154         case EACCES:            return WSAEACCES;
155         case EFAULT:            return WSAEFAULT;
156         case EINVAL:            return WSAEINVAL;
157         case EMFILE:            return WSAEMFILE;
158         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
159         case EINPROGRESS:       return WSAEINPROGRESS;
160         case EALREADY:          return WSAEALREADY;
161         case EBADF:
162         case ENOTSOCK:          return WSAENOTSOCK;
163         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
164         case EMSGSIZE:          return WSAEMSGSIZE;
165         case EPROTOTYPE:        return WSAEPROTOTYPE;
166         case ENOPROTOOPT:       return WSAENOPROTOOPT;
167         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
168         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
169         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
170         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
171         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
172         case EADDRINUSE:        return WSAEADDRINUSE;
173         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
174         case ENETDOWN:          return WSAENETDOWN;
175         case ENETUNREACH:       return WSAENETUNREACH;
176         case ENETRESET:         return WSAENETRESET;
177         case ECONNABORTED:      return WSAECONNABORTED;
178         case ECONNRESET:        return WSAECONNRESET;
179         case ENOBUFS:           return WSAENOBUFS;
180         case EISCONN:           return WSAEISCONN;
181         case ENOTCONN:          return WSAENOTCONN;
182         case ESHUTDOWN:         return WSAESHUTDOWN;
183         case ETOOMANYREFS:      return WSAETOOMANYREFS;
184         case ETIMEDOUT:         return WSAETIMEDOUT;
185         case ECONNREFUSED:      return WSAECONNREFUSED;
186         case ELOOP:             return WSAELOOP;
187         case ENAMETOOLONG:      return WSAENAMETOOLONG;
188         case EHOSTDOWN:         return WSAEHOSTDOWN;
189         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
190         case ENOTEMPTY:         return WSAENOTEMPTY;
191 #ifdef EPROCLIM
192         case EPROCLIM:          return WSAEPROCLIM;
193 #endif
194         case EUSERS:            return WSAEUSERS;
195         case EDQUOT:            return WSAEDQUOT;
196         case ESTALE:            return WSAESTALE;
197         case EREMOTE:           return WSAEREMOTE;
198
199         default:
200                 fprintf(stderr, "winsock: unknown errorno %d!\n", errno);
201                 return WSAEOPNOTSUPP;
202         }
203 }
204
205 static void errno_to_wsaerrno(void)
206 {
207         wsa_errno = wsaerrno();
208 }
209
210 static void convert_sockopt(INT *level, INT *optname)
211 {
212 /* $%#%!@! why couldn't they use the same values for both winsock and unix ? */
213
214         switch (*level) {
215                 case -1: 
216                         *level = SOL_SOCKET;
217                         switch (*optname) {
218                         case 0x01:      *optname = SO_DEBUG;
219                                         break;
220                         case 0x04:      *optname = SO_REUSEADDR;
221                                         break;
222                         case 0x08:      *optname = SO_KEEPALIVE;
223                                         break;
224                         case 0x10:      *optname = SO_DONTROUTE;
225                                         break;
226                         case 0x20:      *optname = SO_BROADCAST;
227                                         break;
228                         case 0x80:      *optname = SO_LINGER;
229                                         break;
230                         case 0x100:     *optname = SO_OOBINLINE;
231                                         break;
232                         case 0x1001:    *optname = SO_SNDBUF;
233                                         break;
234                         case 0x1002:    *optname = SO_RCVBUF;
235                                         break;
236                         case 0x1007:    *optname = SO_ERROR;
237                                         break;
238                         case 0x1008:    *optname = SO_TYPE;
239                                         break;
240                         default: 
241                                         fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
242                                         break;
243                         }
244                         break;
245                 case 6: *optname = IPPROTO_TCP;
246         }
247 }
248
249 #ifndef WINELIB
250 static SEGPTR copy_stringlist(char **list)
251 {
252         SEGPTR *s_list;
253         int i;
254         for(i=0;list[i];i++)
255                 ;
256         s_list = scratch_alloc(sizeof(SEGPTR)*(i+1));
257         for(i=0;list[i];i++)
258         {
259                 void *copy = scratch_alloc(strlen(list[i])+1);
260                 strcpy(copy,list[i]);
261                 s_list[i]=GET_SEG_PTR(copy);
262         }
263         s_list[i]=0;
264         return GET_SEG_PTR(s_list);
265 }
266         
267
268 static void CONVERT_HOSTENT(struct WIN_hostent *heapent, struct hostent *host)
269 {
270         SEGPTR *addr_list;
271         int i;
272         ResetScratch();
273         strcpy(heapent->hostname,host->h_name);
274         heapent->h_name = GET_SEG_PTR(heapent->hostname);
275         /* Convert aliases. Have to create array with FAR pointers */
276         if(!host->h_aliases)
277                 heapent->h_aliases = 0;
278         else
279                 heapent->h_aliases = copy_stringlist(host->h_aliases);
280
281         heapent->h_addrtype = host->h_addrtype;
282         heapent->h_length = host->h_length;
283         for(i=0;host->h_addr_list[i];i++)
284                 ;
285         addr_list=scratch_alloc(sizeof(SEGPTR)*(i+1));
286         heapent->h_addr_list = GET_SEG_PTR(addr_list);
287         for(i=0;host->h_addr_list[i];i++)
288         {
289                 void *addr=scratch_alloc(host->h_length);
290                 memcpy(addr,host->h_addr_list[i],host->h_length);
291                 addr_list[i]=GET_SEG_PTR(addr);
292         }
293         addr_list[i]=0;
294 }
295
296 static void CONVERT_PROTOENT(struct WIN_protoent *heapent, 
297         struct protoent *proto)
298 {
299         ResetScratch();
300         heapent->p_name= scratch_strdup(proto->p_name);
301         heapent->p_aliases=proto->p_aliases ? 
302                         copy_stringlist(proto->p_aliases) : 0;
303         heapent->p_proto = proto->p_proto;
304 }
305
306 static void CONVERT_SERVENT(struct WIN_servent *heapent, struct servent *serv)
307 {
308         ResetScratch();
309         heapent->s_name = scratch_strdup(serv->s_name);
310         heapent->s_aliases = serv->s_aliases ?
311                         copy_stringlist(serv->s_aliases) : 0;
312         heapent->s_port = serv->s_port;
313         heapent->s_proto = scratch_strdup(serv->s_proto);
314 }
315 #else
316 #define CONVERT_HOSTENT(a,b)    memcpy(a, &b, sizeof(a))
317 #define CONVERT_PROTOENT(a,b)   memcpy(a, &b, sizeof(a))
318 #define CONVERT_SERVENT(a,b)    memcpy(a, &b, sizeof(a))
319 #endif
320
321 SOCKET WINSOCK_accept(SOCKET s, struct sockaddr *addr, INT *addrlen)
322 {
323         int sock;
324
325         dprintf_winsock(stddeb, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, *addrlen);
326
327         if ((sock = accept(s, addr, (int *) addrlen)) < 0) {
328                 errno_to_wsaerrno();
329                 return INVALID_SOCKET;
330         }
331         return sock;
332 }
333
334 INT WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
335 {
336         dprintf_winsock(stddeb, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
337         dump_sockaddr(name);
338
339         if (bind(s, name, namelen) < 0) {
340                 errno_to_wsaerrno();
341                 return SOCKET_ERROR;
342         }
343         return 0;
344 }
345
346 INT WINSOCK_closesocket(SOCKET s)
347 {
348         dprintf_winsock(stddeb, "WSA_closesocket: socket %d\n", s);
349
350         FD_CLR(s, &fd_in_use);
351
352         if (close(s) < 0) {
353                 errno_to_wsaerrno();
354                 return SOCKET_ERROR;
355         }
356         return 0;
357 }
358
359 INT WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen)
360 {
361         dprintf_winsock(stddeb, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
362         dump_sockaddr(name);
363
364         if (connect(s, name, namelen) < 0) {
365                 errno_to_wsaerrno();
366                 return SOCKET_ERROR;
367         }
368         return 0;
369 }
370
371 INT WINSOCK_getpeername(SOCKET s, struct sockaddr *name, INT *namelen)
372 {
373         dprintf_winsock(stddeb, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
374         dump_sockaddr(name);
375
376         if (getpeername(s, name, (int *) namelen) < 0) {
377                 errno_to_wsaerrno();
378                 return SOCKET_ERROR;
379         }
380         return 0;
381 }
382
383 INT WINSOCK_getsockname(SOCKET s, struct sockaddr *name, INT *namelen)
384 {
385         dprintf_winsock(stddeb, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
386         if (getsockname(s, name, (int *) namelen) < 0) {
387                 errno_to_wsaerrno();
388                 return SOCKET_ERROR;
389         }
390         return 0;
391 }
392
393 INT
394 WINSOCK_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
395 {
396         dprintf_winsock(stddeb, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen);
397         convert_sockopt(&level, &optname);
398
399         if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) {
400                 errno_to_wsaerrno();
401                 return SOCKET_ERROR;
402         }
403         return 0;
404 }
405
406 u_long WINSOCK_htonl(u_long hostlong)
407 {
408         return( htonl(hostlong) );
409 }         
410
411 u_short WINSOCK_htons(u_short hostshort)
412 {
413         return( htons(hostshort) );
414 }
415
416 u_long WINSOCK_inet_addr(char *cp)
417 {
418         return( inet_addr(cp) );
419 }
420
421 char *WINSOCK_inet_ntoa(struct in_addr in)
422 {
423         char *s;
424
425 /*      dprintf_winsock(stddeb, "WSA_inet_ntoa: %8lx\n", (int) in);*/
426
427         if ((s = inet_ntoa(in)) == NULL) {
428                 errno_to_wsaerrno();
429                 return NULL;
430         }
431
432         strncpy(Heap->ntoa_buffer, s, sizeof(Heap->ntoa_buffer) );
433
434         return (char *) GET_SEG_PTR(&Heap->ntoa_buffer);
435 }
436
437 INT WINSOCK_ioctlsocket(SOCKET s, u_long cmd, u_long *argp)
438 {
439         long newcmd;
440         u_long *newargp;
441         char *ctlname;
442         dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %lX, ptr %8x\n", s, cmd, (int) argp);
443
444         /* Why can't they all use the same ioctl numbers */
445         newcmd=cmd;
446         newargp=argp;
447         ctlname=0;
448         if(cmd == _IOR('f',127,u_long))
449         {
450                 ctlname="FIONREAD";
451                 newcmd=FIONREAD;
452         }else 
453         if(cmd == _IOW('f',126,u_long) || cmd == _IOR('f',126,u_long))
454         {
455                 ctlname="FIONBIO";
456                 newcmd=FIONBIO;
457         }else
458         if(cmd == _IOW('f',125,u_long))
459         {
460                 ctlname="FIOASYNC";
461                 newcmd=FIOASYNC;
462         }
463
464         if(!ctlname)
465                 fprintf(stderr,"Unknown winsock ioctl. Trying anyway\n");
466         else
467                 dprintf_winsock(stddeb,"Recognized as %s\n", ctlname);
468         
469
470         if (ioctl(s, newcmd, newargp) < 0) {
471                 errno_to_wsaerrno();
472                 return SOCKET_ERROR;
473         }
474         return 0;
475 }
476
477 INT WINSOCK_listen(SOCKET s, INT backlog)
478 {
479         dprintf_winsock(stddeb, "WSA_listen: socket %d, backlog %d\n", s, backlog);
480
481         if (listen(s, backlog) < 0) {
482                 errno_to_wsaerrno();
483                 return SOCKET_ERROR;
484         }
485         return 0;
486 }
487
488 u_long WINSOCK_ntohl(u_long netlong)
489 {
490         return( ntohl(netlong) );
491 }
492
493 u_short WINSOCK_ntohs(u_short netshort)
494 {
495         return( ntohs(netshort) );
496 }
497
498 INT WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
499 {
500         int length;
501
502         dprintf_winsock(stddeb, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags);
503
504         if ((length = recv(s, buf, len, flags)) < 0) {
505                 errno_to_wsaerrno();
506                 return SOCKET_ERROR;
507         }
508         return length;
509 }
510
511 INT WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags, 
512                 struct sockaddr *from, int *fromlen)
513 {
514         int length;
515
516         dprintf_winsock(stddeb, "WSA_recvfrom: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long)buf, len, flags);
517
518         if ((length = recvfrom(s, buf, len, flags, from, fromlen)) < 0) {
519                 errno_to_wsaerrno();
520                 return SOCKET_ERROR;
521         }
522         return length;
523 }
524
525 INT WINSOCK_select(INT nfds, fd_set *readfds, fd_set *writefds,
526         fd_set *exceptfds, struct timeval *timeout)
527 {
528         dprintf_winsock(stddeb, "WSA_select: fd # %d, ptr %8lx, ptr %8lx, ptr %8lX\n", nfds, (unsigned long) readfds, (unsigned long) writefds, (unsigned long) exceptfds);
529
530         return(select(nfds, readfds, writefds, exceptfds, timeout));
531 }
532
533 INT WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
534 {
535         int length;
536
537         dprintf_winsock(stddeb, "WSA_send: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
538
539         if ((length = send(s, buf, len, flags)) < 0) {
540                 errno_to_wsaerrno();
541                 return SOCKET_ERROR;
542         }
543         return length;
544 }
545
546 INT WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
547                 struct sockaddr *to, INT tolen)
548 {
549         int length;
550
551         dprintf_winsock(stddeb, "WSA_sendto: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
552
553         if ((length = sendto(s, buf, len, flags, to, tolen)) < 0) {
554                 errno_to_wsaerrno();
555                 return SOCKET_ERROR;
556         }
557         return length;
558 }
559
560 INT WINSOCK_setsockopt(SOCKET s, INT level, INT optname, const char *optval, 
561                         INT optlen)
562 {
563         dprintf_winsock(stddeb, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen);
564         convert_sockopt(&level, &optname);
565         
566         if (setsockopt(s, level, optname, optval, optlen) < 0) {
567                 errno_to_wsaerrno();
568                 return SOCKET_ERROR;
569         }
570         return 0;
571 }                                         
572
573 INT WINSOCK_shutdown(SOCKET s, INT how)
574 {
575         dprintf_winsock(stddeb, "WSA_shutdown: socket s %d, how %d\n", s, how);
576
577         if (shutdown(s, how) < 0) {
578                 errno_to_wsaerrno();
579                 return SOCKET_ERROR;
580         }
581         return 0;
582 }
583
584 SOCKET WINSOCK_socket(INT af, INT type, INT protocol)
585 {
586     int sock;
587
588     dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol);
589
590     if ((sock = socket(af, type, protocol)) < 0) {
591             errno_to_wsaerrno();
592             dprintf_winsock(stddeb, "WSA_socket: failed !\n");
593             return INVALID_SOCKET;
594     }
595     
596     if (sock > 0xffff) {
597         wsa_errno = WSAEMFILE;
598         return INVALID_SOCKET;
599     }
600
601     FD_SET(sock, &fd_in_use);
602
603     dprintf_winsock(stddeb, "WSA_socket: fd %d\n", sock);
604     return sock;
605 }
606
607 /*
608 struct WIN_hostent *
609 */
610 SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
611 {
612         struct hostent *host;
613
614         dprintf_winsock(stddeb, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type);
615
616         if ((host = gethostbyaddr(addr, len, type)) == NULL) {
617                 errno_to_wsaerrno();
618                 return NULL;
619         }
620         CONVERT_HOSTENT(&Heap->hostent_addr, host);
621
622         return GET_SEG_PTR(&Heap->hostent_addr);
623 }
624
625 /*
626 struct WIN_hostent *
627 */
628 SEGPTR WINSOCK_gethostbyname(const char *name)
629 {
630         struct hostent *host;
631
632         dprintf_winsock(stddeb, "WSA_gethostbyname: %s\n", name);
633
634         if ((host = gethostbyname(name)) == NULL) {
635                 errno_to_wsaerrno();
636                 return NULL;
637         }
638         CONVERT_HOSTENT(&Heap->hostent_name, host);
639
640         return GET_SEG_PTR(&Heap->hostent_name);
641 }
642
643 INT WINSOCK_gethostname(char *name, INT namelen)
644 {
645         dprintf_winsock(stddeb, "WSA_gethostname: name %s, len %d\n", name, namelen);
646
647         if (gethostname(name, namelen) < 0) {
648                 errno_to_wsaerrno();
649                 return SOCKET_ERROR;
650         }
651         return 0;
652 }          
653
654 /*
655 struct WIN_protoent *
656 */
657 SEGPTR WINSOCK_getprotobyname(char *name)
658 {
659         struct protoent *proto;
660
661         dprintf_winsock(stddeb, "WSA_getprotobyname: name %s\n", name);
662
663         if ((proto = getprotobyname(name)) == NULL) {
664                 errno_to_wsaerrno();
665                 return NULL;
666         }
667         CONVERT_PROTOENT(&Heap->protoent_name, proto);
668
669         return GET_SEG_PTR(&Heap->protoent_name);
670 }
671
672 /*
673 struct WIN_protoent *
674 */
675 SEGPTR WINSOCK_getprotobynumber(INT number)
676 {
677         struct protoent *proto;
678
679         dprintf_winsock(stddeb, "WSA_getprotobynumber: num %d\n", number);
680
681         if ((proto = getprotobynumber(number)) == NULL) {
682                 errno_to_wsaerrno();
683                 return NULL;
684         }
685         CONVERT_PROTOENT(&Heap->protoent_number, proto);
686
687         return GET_SEG_PTR(&Heap->protoent_number);
688 }
689
690 /*
691 struct WIN_servent *
692 */
693 SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
694 {
695         struct servent *service;
696
697         if (proto == NULL)
698                 proto = "tcp";
699
700         dprintf_winsock(stddeb, "WSA_getservbyname: name %s, proto %s\n", name, proto);
701
702         if ((service = getservbyname(name, proto)) == NULL) {
703                 errno_to_wsaerrno();
704                 return NULL;
705         }
706         CONVERT_SERVENT(&Heap->servent_name, service);
707
708         return GET_SEG_PTR(&Heap->servent_name);
709 }
710
711 /*
712 struct WIN_servent *
713 */
714 SEGPTR WINSOCK_getservbyport(INT port, const char *proto)
715 {
716         struct servent *service;
717
718         dprintf_winsock(stddeb, "WSA_getservbyport: port %d, name %s\n", port, proto);
719
720         if ((service = getservbyport(port, proto)) == NULL) {
721                 errno_to_wsaerrno();
722                 return NULL;
723         }
724         CONVERT_SERVENT(&Heap->servent_port, service);
725
726         return GET_SEG_PTR(&Heap->servent_port);
727 }
728
729 /******************** winsock specific functions ************************
730  *
731  */
732 static HANDLE new_handle = 0;
733
734 static HANDLE AllocWSAHandle(void)
735 {
736         return new_handle++;
737 }
738
739 static void recv_message(int sig)
740 {
741         struct ipc_packet message;
742
743         if (msgrcv(wine_key, &message, IPC_PACKET_SIZE, MTYPE, IPC_NOWAIT) == -1)
744                 perror("wine: msgrcv");
745
746         fprintf(stderr, 
747                 "WSA: PostMessage (hwnd %d, wMsg %d, wParam %d, lParam %ld)\n",
748                 message.hWnd,
749                 message.wMsg,
750                 message.handle,
751                 message.lParam);
752
753         PostMessage(message.hWnd, message.wMsg, message.handle, message.lParam);
754                 
755         signal(SIGUSR1, recv_message);
756 }
757
758
759 static void send_message(HANDLE handle, HWND hWnd, u_int wMsg, long lParam)
760 {
761         struct ipc_packet message;
762         
763         message.mtype = MTYPE;
764         message.handle = handle;
765         message.hWnd = hWnd;
766         message.wMsg = wMsg;
767         message.lParam = lParam;
768
769         fprintf(stderr, 
770                 "WSA: send (hwnd %d, wMsg %d, handle %d, lParam %ld)\n",
771                 hWnd, wMsg, handle, lParam);
772         
773         if (msgsnd(wine_key, &message,  IPC_PACKET_SIZE, IPC_NOWAIT) == -1)
774                 perror("wine: msgsnd");
775                 
776         kill(getppid(), SIGUSR1);
777 }
778
779
780 HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char *addr,
781                  INT len, INT type, char *buf, INT buflen)
782 {
783         HANDLE handle;
784         struct hostent *host;
785
786         handle = AllocWSAHandle();
787
788         if (fork()) {
789                 return handle;
790         } else {
791                 if ((host = gethostbyaddr(addr, len, type)) == NULL) {
792                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
793                         exit(0);
794                 }
795                 memcpy(buf, host, buflen);
796                 send_message(hWnd, wMsg, handle, 0);
797                 exit(0);
798         }
799 }
800
801
802 HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char *name, 
803                         char *buf, INT buflen)
804 {
805         HANDLE handle;
806         struct hostent *host;
807
808         handle = AllocWSAHandle();
809
810         if (fork()) {
811                 return handle;
812         } else {
813                 if ((host = gethostbyname(name)) == NULL) {
814                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
815                         exit(0);
816                 }
817                 memcpy(buf, host, buflen);
818                 send_message(hWnd, wMsg, handle, 0);
819                 exit(0);
820         }
821 }                     
822
823
824 HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, const char *name, 
825                         char *buf, INT buflen)
826 {
827         HANDLE handle;
828         struct protoent *proto;
829
830         handle = AllocWSAHandle();
831
832         if (fork()) {
833                 return handle;
834         } else {
835                 if ((proto = getprotobyname(name)) == NULL) {
836                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
837                         exit(0);
838                 }
839                 memcpy(buf, proto, buflen);
840                 send_message(hWnd, wMsg, handle, 0);
841                 exit(0);
842         }
843 }
844
845
846 HANDLE WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number, 
847                         char *buf, INT buflen)
848 {
849         HANDLE handle;
850         struct protoent *proto;
851
852         handle = AllocWSAHandle();
853
854         if (fork()) {
855                 return handle;
856         } else {
857                 if ((proto = getprotobynumber(number)) == NULL) {
858                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
859                         exit(0);
860                 }
861                 memcpy(buf, proto, buflen);
862                 send_message(hWnd, wMsg, handle, 0);
863                 exit(0);
864         }
865 }
866
867
868 HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, const char *name, 
869                         const char *proto, char *buf, INT buflen)
870 {
871         HANDLE handle;
872         struct servent *service;
873
874         handle = AllocWSAHandle();
875
876         if (fork()) {
877                 return handle;
878         } else {
879                 if ((service = getservbyname(name, proto)) == NULL) {
880                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
881                         exit(0);
882                 }
883                 memcpy(buf, service, buflen);
884                 send_message(hWnd, wMsg, handle, 0);
885                 exit(0);
886         }
887 }
888
889
890 HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char 
891                         *proto, char *buf, INT buflen)
892 {
893         HANDLE handle;
894         struct servent *service;
895
896         handle = AllocWSAHandle();
897
898         if (fork()) {
899                 return handle;
900         } else {
901                 if ((service = getservbyport(port, proto)) == NULL) {
902                         send_message(hWnd, wMsg, handle, wsaerrno() << 16);
903                         exit(0);
904                 }
905                 memcpy(buf, service, buflen);
906                 send_message(hWnd, wMsg, handle, 0);
907                 exit(0);
908         }
909 }
910
911 INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent)
912 {
913         long event;
914         fd_set read_fds, write_fds, except_fds;
915
916         dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND %d, wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
917
918         /* remove outstanding asyncselect() processes */
919         /* kill */
920
921         if (wMsg == 0 && lEvent == 0) 
922                 return 0;
923
924         if (fork()) {
925                 return 0;
926         } else {
927                 while (1) {
928                         FD_ZERO(&read_fds);
929                         FD_ZERO(&write_fds);
930                         FD_ZERO(&except_fds);
931
932                         if (lEvent & FD_READ)
933                                 FD_SET(s, &read_fds);
934                         if (lEvent & FD_WRITE)
935                                 FD_SET(s, &write_fds);
936
937                         fcntl(s, F_SETFL, O_NONBLOCK);
938                         select(s + 1, &read_fds, &write_fds, &except_fds, NULL);
939
940                         event = 0;
941                         if (FD_ISSET(s, &read_fds))
942                                 event |= FD_READ;
943                         if (FD_ISSET(s, &write_fds))
944                                 event |= FD_WRITE;
945
946                         send_message(hWnd, wMsg, s, (wsaerrno() << 16) | event);
947                 }
948         }
949 }
950
951 INT WSAFDIsSet(INT fd, fd_set *set)
952 {
953         return( FD_ISSET(fd, set) );
954 }
955
956 INT WSACancelAsyncRequest(HANDLE hAsyncTaskHandle)
957 {
958         dprintf_winsock(stddeb, "WSA_AsyncRequest: handle %d\n", hAsyncTaskHandle);
959
960         return 0;
961 }
962
963 INT WSACancelBlockingCall(void)
964 {
965         dprintf_winsock(stddeb, "WSA_CancelBlockCall\n");
966         return 0;
967 }
968           
969 INT WSAGetLastError(void)
970 {
971         dprintf_winsock(stddeb, "WSA_GetLastError = %x\n", wsa_errno);
972
973     return wsa_errno;
974 }
975
976 void WSASetLastError(INT iError)
977 {
978         dprintf_winsock(stddeb, "WSA_SetLastErorr %d\n", iError);
979
980     wsa_errno = iError;
981 }
982
983 BOOL WSAIsBlocking(void)
984 {
985         dprintf_winsock(stddeb, "WSA_IsBlocking\n");
986
987         return 0;
988 }
989
990 FARPROC WSASetBlockingHook(FARPROC lpBlockFunc)
991 {
992         dprintf_winsock(stddeb, "WSA_SetBlockHook %8lx, STUB!\n", (unsigned long) lpBlockFunc);
993         BlockFunction = lpBlockFunc;
994
995         return (FARPROC) lpBlockFunc;
996 }
997
998 INT WSAUnhookBlockingHook(void)
999 {
1000         dprintf_winsock(stddeb, "WSA_UnhookBlockingHook\n");
1001         BlockFunction = NULL;
1002
1003         return 0;
1004 }
1005
1006 WSADATA WINSOCK_data = {
1007         0x0101,
1008         0x0101,
1009         "WINE Sockets",
1010 #ifdef linux
1011         "LINUX/i386",
1012 #endif
1013 #ifdef __NetBSD__
1014         "NetBSD/i386",
1015 #endif
1016 #ifdef sunos
1017         "SunOS",
1018 #endif
1019         128,
1020         1024,
1021         NULL
1022 };
1023
1024 INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
1025 {
1026
1027     dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
1028
1029     if (LOBYTE(wVersionRequested) < 1 ||
1030         (LOBYTE(wVersionRequested) == 1 &&
1031          HIBYTE(wVersionRequested) < 1))
1032         return WSAVERNOTSUPPORTED;
1033
1034     if (!lpWSAData)
1035         return WSAEINVAL;
1036
1037         /* alloc winsock heap */
1038
1039     if ((HeapHandle = GlobalAlloc(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0)
1040         return WSASYSNOTREADY;
1041
1042     Heap = (struct WinSockHeap *) GlobalLock(HeapHandle);
1043     bcopy(&WINSOCK_data, lpWSAData, sizeof(WINSOCK_data));
1044
1045     /* ipc stuff */
1046
1047     if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
1048         perror("wine: msgget");
1049
1050     signal(SIGUSR1, recv_message);
1051
1052     /* clear */
1053     
1054     FD_ZERO(&fd_in_use);
1055
1056     wsa_initted = 1;
1057     return(0);
1058 }
1059
1060 INT WSACleanup(void)
1061 {
1062         int fd;
1063
1064         if (wine_key)
1065                 if (msgctl(wine_key, IPC_RMID, NULL) == -1)
1066                         perror("wine: shmctl");
1067
1068         for (fd = 0; fd != FD_SETSIZE; fd++)
1069                 if (FD_ISSET(fd, &fd_in_use))
1070                         close(fd);
1071
1072         wsa_initted = 0;
1073         return 0;
1074 }