]> git.pond.sub.org Git - empserver/blob - src/client/sysdep_w32.c
Use src/lib/w32/w32io.c for client
[empserver] / src / client / sysdep_w32.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  sysdep_w32.c: system dependent functions for WIN32 environments
29  *
30  *  Known contributors to this file:
31  *     Ron Koenderink, 2007
32  *     Markus Armbruster, 2009
33  */
34
35 #ifdef _WIN32
36 #include <errno.h>
37 #include <fcntl.h>
38 #include "misc.h"
39
40 static int
41 fd_is_socket(int fd, SOCKET *sockp)
42 {
43     SOCKET sock;
44     WSANETWORKEVENTS ev;
45
46     sock = W32_FD_TO_SOCKET(fd);
47     if (sockp)
48         *sockp = sock;
49     return WSAEnumNetworkEvents(sock, NULL, &ev) == 0;
50 }
51
52 void
53 w32_set_winsock_errno(void)
54 {
55   int err = WSAGetLastError();
56   WSASetLastError(0);
57
58   /* Map some WSAE* errors to the runtime library's error codes.  */
59   switch (err)
60     {
61     case WSA_INVALID_HANDLE:
62       errno = EBADF;
63       break;
64     case WSA_NOT_ENOUGH_MEMORY:
65       errno = ENOMEM;
66       break;
67     case WSA_INVALID_PARAMETER:
68       errno = EINVAL;
69       break;
70     case WSAEWOULDBLOCK:
71       errno = EAGAIN;
72       break;
73     case WSAENAMETOOLONG:
74       errno = ENAMETOOLONG;
75       break;
76     case WSAENOTEMPTY:
77       errno = ENOTEMPTY;
78       break;
79     default:
80       errno = (err > 10000 && err < 10025) ? err - 10000 : err;
81       break;
82     }
83 }
84
85 /*
86  * Get user name in the WIN32 environment
87  */
88 struct passwd *
89 w32_getpw(void)
90 {
91     static char unamebuf[128];
92     static struct passwd pwd;
93     DWORD unamesize;
94
95     unamesize = sizeof(unamebuf);
96     if (GetUserName(unamebuf, &unamesize)) {
97         pwd.pw_name = unamebuf;
98         if (unamesize == 0 || strlen(unamebuf) == 0)
99             pwd.pw_name = "nobody";
100     } else
101         pwd.pw_name = "nobody";
102     return &pwd;
103 }
104
105 /*
106  * Initialize the WIN32 socket library and
107  * set up stdout to work around bugs
108  */
109 void
110 w32_sysdep_init(void)
111 {
112     int err;
113     WSADATA WsaData;
114     /*
115      * stdout is unbuffered under Windows if connected to a character
116      * device, and putchar() screws up when printing multibyte strings
117      * bytewise to an unbuffered stream.  Switch stdout to line-
118      * buffered mode.  Unfortunately, ISO C allows implementations to
119      * screw that up, and of course Windows does.  Manual flushing
120      * after each prompt is required.
121      */
122     setvbuf(stdout, NULL, _IOLBF, 4096);
123     err = WSAStartup(MAKEWORD(2, 0), &WsaData);
124     if (err != 0) {
125         printf("WSAStartup Failed, error code %d\n", err);
126         exit(1);
127     }
128 }
129
130 /*
131  * POSIX compatible socket() replacement
132  */
133 #undef socket
134 int
135 w32_socket(int domain, int type, int protocol)
136 {
137     SOCKET sock;
138
139     /*
140      * We have to use WSASocket() to create non-overlapped IO sockets.
141      * Overlapped IO sockets cannot be used with read/write.
142      */
143     sock = WSASocket(domain, type, protocol, NULL, 0, 0);
144     if (sock == INVALID_SOCKET) {
145         w32_set_winsock_errno();
146         return -1;
147     }
148     return W32_SOCKET_TO_FD(sock);
149 }
150
151 /*
152  * POSIX compatible connect() replacement
153  */
154 #undef connect
155 int
156 w32_connect(int sockfd, const struct sockaddr *addr, int addrlen)
157 {
158     SOCKET sock = W32_FD_TO_SOCKET(sockfd);
159     int result;
160
161     result = connect(sock, addr, addrlen);
162     if (result == SOCKET_ERROR) {
163         /* FIXME map WSAEWOULDBLOCK to EINPROGRESS */
164         w32_set_winsock_errno();
165         return -1;
166     }
167     return result;
168 }
169
170 /*
171  * POSIX compatible recv() replacement
172  */
173 #undef recv
174 int
175 w32_recv(int sockfd, void *buffer, size_t buf_size, int flags)
176 {
177     SOCKET socket = W32_FD_TO_SOCKET(sockfd);
178     int result;
179
180     result = recv(socket, buffer, buf_size, flags);
181     if (result == SOCKET_ERROR) {
182         w32_set_winsock_errno();
183         return -1;
184     }
185     return result;
186 }
187
188 /*
189  * POSIX compatible send() replacement
190  */
191 int
192 w32_send(int sockfd, const void *buffer, size_t buf_size, int flags)
193 {
194     SOCKET socket = W32_FD_TO_SOCKET(sockfd);
195     int result;
196
197     result = send(socket, buffer, buf_size, flags);
198     if (result == SOCKET_ERROR)
199         w32_set_winsock_errno();
200     return result;
201 }
202
203 /*
204  * POSIX compatible close() replacement
205  */
206 int
207 w32_close(int fd)
208 {
209     SOCKET sock;
210
211     if (fd_is_socket(fd, &sock)) {
212         if (closesocket(sock)) {
213             w32_set_winsock_errno();
214             return -1;
215         }
216         /*
217          * This always fails because the underlying handle is already
218          * gone, but it closes the fd just fine.
219          */
220         _close(fd);
221         return 0;
222     }
223     return _close(fd);
224 }
225
226 #endif /* _WIN32 */