Add getusershell(), setusershell(), endusershell() declarations to <unistd.h>.
[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 <stdarg.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <io.h>
27 #include <sys/socket.h>
28 #if GNULIB_IOCTL
29 #include <sys/ioctl.h>
30 #endif
31
32 #undef socket
33 #undef connect
34 #undef accept
35 #undef bind
36 #undef getpeername
37 #undef getsockname
38 #undef getsockopt
39 #undef listen
40 #undef recv
41 #undef send
42 #undef recvfrom
43 #undef sendto
44 #undef setsockopt
45 #undef shutdown
46
47 #define FD_TO_SOCKET(fd)   ((SOCKET) _get_osfhandle ((fd)))
48 #define SOCKET_TO_FD(fh)   (_open_osfhandle ((long) (fh), O_RDWR | O_BINARY))
49
50
51 static inline void
52 set_winsock_errno (void)
53 {
54   int err = WSAGetLastError ();
55   WSASetLastError (0);
56
57   /* Map some WSAE* errors to the runtime library's error codes.  */
58   switch (err)
59     {
60     case WSA_INVALID_HANDLE:
61       errno = EBADF;
62       break;
63     case WSA_NOT_ENOUGH_MEMORY:
64       errno = ENOMEM;
65       break;
66     case WSA_INVALID_PARAMETER:
67       errno = EINVAL;
68       break;
69     case WSAEWOULDBLOCK:
70       errno = EWOULDBLOCK;
71       break;
72     case WSAENAMETOOLONG:
73       errno = ENAMETOOLONG;
74       break;
75     case WSAENOTEMPTY:
76       errno = ENOTEMPTY;
77       break;
78     default:
79       errno = (err > 10000 && err < 10025) ? err - 10000 : err;
80       break;
81     }
82 }
83
84
85 /* Hook for gnulib module close.  */
86
87 #if HAVE__GL_CLOSE_FD_MAYBE_SOCKET
88 int
89 _gl_close_fd_maybe_socket (int fd)
90 {
91   SOCKET sock = FD_TO_SOCKET (fd);
92   WSANETWORKEVENTS ev;
93
94   ev.lNetworkEvents = 0xDEADBEEF;
95   WSAEnumNetworkEvents (sock, NULL, &ev);
96   if (ev.lNetworkEvents != 0xDEADBEEF)
97     {
98       /* FIXME: other applications, like squid, use an undocumented
99          _free_osfhnd free function.  But this is not enough: The 'osfile'
100          flags for fd also needs to be cleared, but it is hard to access it.
101          Instead, here we just close twice the file descriptor.  */
102       if (closesocket (sock))
103         {
104           set_winsock_errno ();
105           return -1;
106         }
107       else
108         {
109           /* This call frees the file descriptor and does a
110              CloseHandle ((HANDLE) _get_osfhandle (fd)), which fails.  */
111           _close (fd);
112           return 0;
113         }
114     }
115   else
116     return _close (fd);
117 }
118 #endif
119
120
121 /* Wrappers for WinSock functions.  */
122
123 #if GNULIB_SOCKET
124 int
125 rpl_socket (int domain, int type, int protocol)
126 {
127   /* We have to use WSASocket() to create non-overlapped IO sockets.
128      Overlapped IO sockets cannot be used with read/write.  */
129   SOCKET fh = WSASocket (domain, type, protocol, NULL, 0, 0);
130
131   if (fh == INVALID_SOCKET)
132     {
133       set_winsock_errno ();
134       return -1;
135     }
136   else
137     return SOCKET_TO_FD (fh);
138 }
139 #endif
140
141 #if GNULIB_CONNECT
142 int
143 rpl_connect (int fd, struct sockaddr *sockaddr, int len)
144 {
145   SOCKET sock = FD_TO_SOCKET (fd);
146   int r = connect (sock, sockaddr, len);
147   if (r < 0)
148     {
149       /* EINPROGRESS is not returned by WinSock 2.0; for backwards
150          compatibility, connect(2) uses EWOULDBLOCK.  */
151       if (WSAGetLastError () == WSAEWOULDBLOCK)
152         WSASetLastError (WSAEINPROGRESS);
153
154       set_winsock_errno ();
155     }
156
157   return r;
158 }
159 #endif
160
161 #if GNULIB_ACCEPT
162 int
163 rpl_accept (int fd, struct sockaddr *addr, int *addrlen)
164 {
165   SOCKET fh = accept (FD_TO_SOCKET (fd), addr, addrlen);
166   if (fh == INVALID_SOCKET)
167     {
168       set_winsock_errno ();
169       return -1;
170     }
171   else
172     return SOCKET_TO_FD (fh);
173 }
174 #endif
175
176 #if GNULIB_BIND
177 int
178 rpl_bind (int fd, struct sockaddr *sockaddr, int len)
179 {
180   SOCKET sock = FD_TO_SOCKET (fd);
181   int r = bind (sock, sockaddr, len);
182   if (r < 0)
183     set_winsock_errno ();
184
185   return r;
186 }
187 #endif
188
189 #if GNULIB_GETPEERNAME
190 int
191 rpl_getpeername (int fd, struct sockaddr *addr, int *addrlen)
192 {
193   SOCKET sock = FD_TO_SOCKET (fd);
194   int r = getpeername (sock, addr, addrlen);
195   if (r < 0)
196     set_winsock_errno ();
197
198   return r;
199 }
200 #endif
201
202 #if GNULIB_GETSOCKNAME
203 int
204 rpl_getsockname (int fd, struct sockaddr *addr, int *addrlen)
205 {
206   SOCKET sock = FD_TO_SOCKET (fd);
207   int r = getsockname (sock, addr, addrlen);
208   if (r < 0)
209     set_winsock_errno ();
210
211   return r;
212 }
213 #endif
214
215 #if GNULIB_GETSOCKOPT
216 int
217 rpl_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
218 {
219   SOCKET sock = FD_TO_SOCKET (fd);
220   int r = getsockopt (sock, level, optname, optval, optlen);
221   if (r < 0)
222     set_winsock_errno ();
223
224   return r;
225 }
226 #endif
227
228 #if GNULIB_LISTEN
229 int
230 rpl_listen (int fd, int backlog)
231 {
232   SOCKET sock = FD_TO_SOCKET (fd);
233   int r = listen (sock, backlog);
234   if (r < 0)
235     set_winsock_errno ();
236
237   return r;
238 }
239 #endif
240
241 #if GNULIB_IOCTL
242 int
243 rpl_ioctl (int fd, int req, ...)
244 {
245   void *buf;
246   va_list args;
247   SOCKET sock;
248   int r;
249
250   va_start (args, req);
251   buf = va_arg (args, void *);
252   va_end (args);
253
254   sock = FD_TO_SOCKET (fd);
255   r = ioctlsocket (sock, req, buf);
256   if (r < 0)
257     set_winsock_errno ();
258
259   return r;
260 }
261 #endif
262
263 #if GNULIB_RECV
264 int
265 rpl_recv (int fd, void *buf, int len, int flags)
266 {
267   SOCKET sock = FD_TO_SOCKET (fd);
268   int r = recv (sock, buf, len, flags);
269   if (r < 0)
270     set_winsock_errno ();
271
272   return r;
273 }
274 #endif
275
276 #if GNULIB_SEND
277 int
278 rpl_send (int fd, const void *buf, int len, int flags)
279 {
280   SOCKET sock = FD_TO_SOCKET (fd);
281   int r = send (sock, buf, len, flags);
282   if (r < 0)
283     set_winsock_errno ();
284
285   return r;
286 }
287 #endif
288
289 #if GNULIB_RECVFROM
290 int
291 rpl_recvfrom (int fd, void *buf, int len, int flags, struct sockaddr *from,
292               int *fromlen)
293 {
294   int frombufsize = *fromlen;
295   SOCKET sock = FD_TO_SOCKET (fd);
296   int r = recvfrom (sock, buf, len, flags, from, fromlen);
297
298   if (r < 0)
299     set_winsock_errno ();
300
301   /* Winsock recvfrom() only returns a valid 'from' when the socket is
302      connectionless.  POSIX gives a valid 'from' for all types of sockets.  */
303   else if (*fromlen == frombufsize)
304     rpl_getpeername (fd, from, fromlen);
305
306   return r;
307 }
308 #endif
309
310 #if GNULIB_SENDTO
311 int
312 rpl_sendto (int fd, const void *buf, int len, int flags,
313             struct sockaddr *to, int tolen)
314 {
315   SOCKET sock = FD_TO_SOCKET (fd);
316   int r = sendto (sock, buf, len, flags, to, tolen);
317   if (r < 0)
318     set_winsock_errno ();
319
320   return r;
321 }
322 #endif
323
324 #if GNULIB_SETSOCKOPT
325 int
326 rpl_setsockopt (int fd, int level, int optname, const void *optval, int optlen)
327 {
328   SOCKET sock = FD_TO_SOCKET (fd);
329   int r = setsockopt (sock, level, optname, optval, optlen);
330   if (r < 0)
331     set_winsock_errno ();
332
333   return r;
334 }
335 #endif
336
337 #if GNULIB_SHUTDOWN
338 int
339 rpl_shutdown (int fd, int how)
340 {
341   SOCKET sock = FD_TO_SOCKET (fd);
342   int r = shutdown (sock, how);
343   if (r < 0)
344     set_winsock_errno ();
345
346   return r;
347 }
348 #endif