Add pmccabe2html to MODULES.html.sh.
[pspp] / lib / winsock.c
1 /* winsock.c --- wrappers for Windows socket functions
2
3    Copyright (C) 2008 Free Software Foundation, Inc.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 /* Written by Paolo Bonzini */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <io.h>
26 #include <sys/socket.h>
27
28 #undef close
29 #undef socket
30 #undef connect
31 #undef accept
32 #undef bind
33 #undef getpeername
34 #undef getsockname
35 #undef getsockopt
36 #undef listen
37 #undef recv
38 #undef send
39 #undef recvfrom
40 #undef sendto
41 #undef setsockopt
42
43 # define FD_TO_SOCKET(fd)   ((SOCKET) _get_osfhandle ((fd)))
44 # define SOCKET_TO_FD(fh)   (_open_osfhandle ((long) (fh), O_RDWR | O_BINARY))
45
46
47 /* Wrappers for libc functions.  */
48
49 int
50 rpl_close (int fd)
51 {
52   SOCKET sock = FD_TO_SOCKET (fd);
53   WSANETWORKEVENTS ev;
54
55   ev.lNetworkEvents = 0xDEADBEEF;
56   WSAEnumNetworkEvents (sock, NULL, &ev);
57   if (ev.lNetworkEvents != 0xDEADBEEF)
58     {
59       /* FIXME: other applications, like squid, use an undocumented
60          _free_osfhnd free function.  Instead, here we just close twice
61          the file descriptor.  I could not get the former to work
62          (pb, Sep 22 2008).  */
63       int r = closesocket (sock);
64       _close (fd);
65       return r;
66     }
67   else
68     return _close (fd);
69 }
70
71
72 /* Wrappers for WinSock functions.  */
73
74 static inline void
75 set_winsock_errno (void)
76 {
77   int err = WSAGetLastError ();
78   WSASetLastError (0);
79
80   /* Map some WSAE* errors to the runtime library's error codes.  */
81   switch (err)
82     {
83     case WSA_INVALID_HANDLE:
84       errno = EBADF;
85       break;
86     case WSA_NOT_ENOUGH_MEMORY:
87       errno = ENOMEM;
88       break;
89     case WSA_INVALID_PARAMETER:
90       errno = EINVAL;
91       break;
92     case WSAEWOULDBLOCK:
93       errno = EWOULDBLOCK;
94       break;
95     case WSAENAMETOOLONG:
96       errno = ENAMETOOLONG;
97       break;
98     case WSAENOTEMPTY:
99       errno = ENOTEMPTY;
100       break;
101     default:
102       errno = (err > 10000 && err < 10025) ? err - 10000 : err;
103       break;
104     }
105 }
106
107 #if GNULIB_SOCKET
108 int
109 rpl_socket (int domain, int type, int protocol)
110 {
111   /* We have to use WSASocket() to create non-overlapped IO sockets.
112      Overlapped IO sockets cannot be used with read/write.  */
113   SOCKET fh = WSASocket (domain, type, protocol, NULL, 0, 0);
114
115   if (fh == INVALID_SOCKET)
116     {
117       set_winsock_errno ();
118       return -1;
119     }
120   else
121     return SOCKET_TO_FD (fh);
122 }
123 #endif
124
125 #if GNULIB_CONNECT
126 int
127 rpl_connect (int fd, struct sockaddr *sockaddr, int len)
128 {
129   SOCKET sock = FD_TO_SOCKET (fd);
130   int r = connect (sock, sockaddr, len);
131   if (r < 0)
132     {
133       /* EINPROGRESS is not returned by WinSock 2.0; for backwards
134          compatibility, connect(2) uses EWOULDBLOCK.  */
135       if (WSAGetLastError () == WSAEWOULDBLOCK)
136         WSASetLastError (WSAEINPROGRESS);
137
138       set_winsock_errno ();
139     }
140
141   return r;
142 }
143 #endif
144
145 #if GNULIB_ACCEPT
146 int
147 rpl_accept (int fd, struct sockaddr *addr, int *addrlen)
148 {
149   SOCKET fh = accept (FD_TO_SOCKET (fd), addr, addrlen);
150   if (fh == INVALID_SOCKET)
151     {
152       set_winsock_errno ();
153       return -1;
154     }
155   else
156     return SOCKET_TO_FD (fh);
157 }
158 #endif
159
160 #if GNULIB_BIND
161 int
162 rpl_bind (int fd, struct sockaddr *sockaddr, int len)
163 {
164   SOCKET sock = FD_TO_SOCKET (fd);
165   int r = bind (sock, sockaddr, len);
166   if (r < 0)
167     set_winsock_errno ();
168
169   return r;
170 }
171 #endif
172
173 #if GNULIB_GETPEERNAME
174 int
175 rpl_getpeername (int fd, struct sockaddr *addr, int *addrlen)
176 {
177   SOCKET sock = FD_TO_SOCKET (fd);
178   int r = getpeername (sock, addr, addrlen);
179   if (r < 0)
180     set_winsock_errno ();
181
182   return r;
183 }
184 #endif
185
186 #if GNULIB_GETSOCKNAME
187 int
188 rpl_getsockname (int fd, struct sockaddr *addr, int *addrlen)
189 {
190   SOCKET sock = FD_TO_SOCKET (fd);
191   int r = getsockname (sock, addr, addrlen);
192   if (r < 0)
193     set_winsock_errno ();
194
195   return r;
196 }
197 #endif
198
199 #if GNULIB_GETSOCKOPT
200 int
201 rpl_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
202 {
203   SOCKET sock = FD_TO_SOCKET (fd);
204   int r = getsockopt (sock, level, optname, optval, optlen);
205   if (r < 0)
206     set_winsock_errno ();
207
208   return r;
209 }
210 #endif
211
212 #if GNULIB_LISTEN
213 int
214 rpl_listen (int fd, int backlog)
215 {
216   SOCKET sock = FD_TO_SOCKET (fd);
217   int r = listen (sock, backlog);
218   if (r < 0)
219     set_winsock_errno ();
220
221   return r;
222 }
223 #endif
224
225 int
226 rpl_ioctl (int fd, unsigned long req, char *buf)
227 {
228   SOCKET sock = FD_TO_SOCKET (fd);
229   int r = ioctlsocket (sock, req, (void *) buf);
230   if (r < 0)
231     set_winsock_errno ();
232
233   return r;
234 }
235
236 #if GNULIB_RECV
237 int
238 rpl_recv (int fd, void *buf, int len, int flags)
239 {
240   SOCKET sock = FD_TO_SOCKET (fd);
241   int r = recv (sock, buf, len, flags);
242   if (r < 0)
243     set_winsock_errno ();
244
245   return r;
246 }
247 #endif
248
249 #if GNULIB_SEND
250 int
251 rpl_send (int fd, const void *buf, int len, int flags)
252 {
253   SOCKET sock = FD_TO_SOCKET (fd);
254   int r = send (sock, buf, len, flags);
255   if (r < 0)
256     set_winsock_errno ();
257
258   return r;
259 }
260 #endif
261
262 #if GNULIB_RECVFROM
263 int
264 rpl_recvfrom (int fd, void *buf, int len, int flags, struct sockaddr *from,
265               int *fromlen)
266 {
267   int frombufsize = *fromlen;
268   SOCKET sock = FD_TO_SOCKET (fd);
269   int r = recvfrom (sock, buf, len, flags, from, fromlen);
270
271   if (r < 0)
272     set_winsock_errno ();
273
274   /* Winsock recvfrom() only returns a valid 'from' when the socket is
275      connectionless.  POSIX gives a valid 'from' for all types of sockets.  */
276   else if (*fromlen == frombufsize)
277     rpl_getpeername (fd, from, fromlen);
278
279   return r;
280 }
281 #endif
282
283 #if GNULIB_SENDTO
284 int
285 rpl_sendto (int fd, const void *buf, int len, int flags,
286             struct sockaddr *to, int tolen)
287 {
288   SOCKET sock = FD_TO_SOCKET (fd);
289   int r = sendto (sock, buf, len, flags, to, tolen);
290   if (r < 0)
291     set_winsock_errno ();
292
293   return r;
294 }
295 #endif
296
297 #if GNULIB_SETSOCKOPT
298 int
299 rpl_setsockopt (int fd, int level, int optname, const void *optval, int optlen)
300 {
301   SOCKET sock = FD_TO_SOCKET (fd);
302   int r = setsockopt (sock, level, optname, optval, optlen);
303   if (r < 0)
304     set_winsock_errno ();
305
306   return r;
307 }
308 #endif