]> git.pond.sub.org Git - empserver/blob - src/client/sysdep_w32.c
Replace missing getpass()
[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  */
33
34 #ifdef _WIN32
35 #include <assert.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <io.h>
39 #include <sys/stat.h>
40 #include "misc.h"
41 #include "linebuf.h"
42 #include "ringbuf.h"
43 #include "secure.h"
44
45 /*
46  * Get user name in the WIN32 environment
47  */
48 struct passwd *
49 w32_getpw(void)
50 {
51     static char unamebuf[128];
52     static struct passwd pwd;
53     long unamesize;
54
55     unamesize = sizeof(unamebuf);
56     if (GetUserName(unamebuf, &unamesize)) {
57         pwd.pw_name = unamebuf;
58         if ((unamesize <= 0 ) || (strlen(unamebuf) <= 0))
59             pwd.pw_name = "nobody";
60     } else
61         pwd.pw_name = "nobody";
62     return &pwd;
63 }
64
65 /*
66  * Initialize the WIN32 socket library and
67  * set up stdout to work around bugs
68  */
69 void
70 sysdep_init(void)
71 {
72     int err;
73     WSADATA WsaData;
74     /*
75      * stdout is unbuffered under Windows if connected to a character
76      * device, and putchar() screws up when printing multibyte strings
77      * bytewise to an unbuffered stream.  Switch stdout to line-
78      * buffered mode.  Unfortunately, ISO C allows implementations to
79      * screw that up, and of course Windows does.  Manual flushing
80      * after each prompt is required.
81      */
82     setvbuf(stdout, NULL, _IOLBF, 4096);
83     err = WSAStartup(MAKEWORD(2, 0), &WsaData);
84     if (err != 0) {
85         printf("WSAStartup Failed, error code %d\n", err);
86         exit(1);
87     }
88 }
89
90 /*
91  * POSIX compatible socket() replacement
92  */
93 #undef socket
94 int
95 w32_socket(int family, int sock_type, int protocol)
96 {
97     SOCKET result;
98
99     result = socket(family, sock_type, protocol);
100     if (result == INVALID_SOCKET) {
101         errno = WSAGetLastError();
102         return -1;
103     }
104     return (int)result;
105 }
106
107 /*
108  * POSIX compatible connect() replacement
109  */
110 #undef connect
111 int
112 w32_connect(int sock, struct sockaddr *addr, int addrlen)
113 {
114     int result;
115
116     result = connect(sock,  addr, addrlen);
117     if (result == SOCKET_ERROR) {
118         errno = WSAGetLastError();
119         return -1;
120     }
121     return result;
122 }
123
124 /*
125  * POSIX compatible recv() replacement
126  */
127 #undef recv
128 int
129 w32_recv(int socket, char *buffer, size_t buf_size, int flags)
130 {
131     int result;
132
133     result = recv(socket, buffer, buf_size, flags);
134     if (result == SOCKET_ERROR) {
135         errno = WSAGetLastError();
136         return -1;
137     }
138     return result;
139 }
140
141 /*
142  * POSIX compatible writev() replacement specialized to sockets
143  * Modelled after the GNU's libc/sysdeps/posix/writev.c
144  */
145 ssize_t
146 w32_writev_socket(int fd, const struct iovec *iov, int iovcnt)
147 {
148     int i;
149     unsigned char *buffer, *buffer_location;
150     size_t total_bytes = 0;
151     int bytes_written;
152
153     for (i = 0; i < iovcnt; i++)
154         total_bytes += iov[i].iov_len;
155
156     buffer = malloc(total_bytes);
157     if (buffer == NULL && total_bytes != 0) {
158         errno = ENOMEM;
159         return -1;
160     }
161
162     buffer_location = buffer;
163     for (i = 0; i < iovcnt; i++) {
164         memcpy(buffer_location, iov[i].iov_base, iov[i].iov_len);
165         buffer_location += iov[i].iov_len;
166     }
167
168     bytes_written = send(fd, buffer, total_bytes, 0);
169
170     free(buffer);
171
172     if (bytes_written == SOCKET_ERROR) {
173         errno = WSAGetLastError();
174         return -1;
175     }
176     return bytes_written;
177 }
178
179 /*
180  * POSIX compatible send() replacement
181  */
182 int
183 w32_send(int socket, char *buffer, size_t buf_size, int flags)
184 {
185         int result;
186
187         result = send(socket, buffer, buf_size, flags);
188         if (result == SOCKET_ERROR)
189                 errno = WSAGetLastError();
190         return result;
191 }
192
193 /*
194  * POSIX compatible close() replacement specialized to sockets.
195  */
196 int
197 w32_close_socket(int fd)
198 {
199     int result;
200
201     result = closesocket(fd);
202     if (result == SOCKET_ERROR)
203         errno = WSAGetLastError();
204     return result;
205 }
206
207 /*
208  * POSIX compatible open() replacement
209  */
210 int
211 w32_openfd(const char *fname, int oflag, ...)
212 {
213     va_list ap;
214     int pmode = 0;
215     int fd;
216     int create_permission = 0;
217
218     if (oflag & O_CREAT) {
219         va_start(ap, oflag);
220         pmode = va_arg(ap, int);
221         va_end(ap);
222
223         if (pmode & 0400)
224             create_permission |= _S_IREAD;
225         if (pmode & 0200)
226             create_permission |= _S_IWRITE;
227     }
228
229     fd = _open(fname, oflag, create_permission);
230     return fd;
231 }
232 /*
233  * Open a file for reading, return its handle.
234  * This can be used in place of open() when a handle is desired for
235  * waiting on it with WaitForMultipleObjects() or similar.
236  * Ensure the handle is not zero in order to prevent a problem
237  * input_fd.
238  */
239 int
240 w32_openhandle(const char *fname, int oflag)
241 {
242     HANDLE handle;
243
244     handle = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL,
245         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
246
247     if (handle == INVALID_HANDLE_VALUE) {
248         errno = GetLastError();
249         return -1;
250     }
251     if (handle == 0) {
252         HANDLE dup_handle;
253         if (!DuplicateHandle(GetCurrentProcess(), handle,
254                         GetCurrentProcess(), &dup_handle,
255                         0, FALSE, DUPLICATE_SAME_ACCESS)) {
256             errno = GetLastError();
257             return -1;
258         } else {
259             CloseHandle(handle);
260             handle = dup_handle;
261         }
262     }
263     return (int)handle;
264 }
265
266 /*
267  * POSIX compatible readv() replacement specialized to files.
268  * Modelled after the GNU's libc/sysdeps/posix/readv.c
269  */
270 ssize_t
271 w32_readv_handle(int fd, const struct iovec *iov, int iovcnt)
272 {
273     int i;
274     unsigned char *buffer, *buffer_location;
275     size_t total_bytes = 0;
276     DWORD bytes_read;
277     size_t bytes_left;
278
279     for (i = 0; i < iovcnt; i++) {
280         total_bytes += iov[i].iov_len;
281     }
282
283     buffer = malloc(total_bytes);
284     if (buffer == NULL && total_bytes != 0) {
285         errno = ENOMEM;
286         return -1;
287     }
288
289     if (!ReadFile((HANDLE)fd, buffer, total_bytes, &bytes_read, NULL)) {
290         free(buffer);
291         errno = GetLastError();
292         return -1;
293     }
294
295     bytes_left = bytes_read;
296     buffer_location = buffer;
297     for (i = 0; i < iovcnt; i++) {
298         size_t copy = MIN(iov[i].iov_len, bytes_left);
299
300         memcpy(iov[i].iov_base, buffer_location, copy);
301
302         buffer_location += copy;
303         bytes_left -= copy;
304         if (bytes_left == 0)
305             break;
306     }
307
308     free(buffer);
309
310     return bytes_read;
311 }
312
313 /*
314  * POSIX compatible close() replacement specialized to files.
315  * Hack: expects a handle, cannot be used with a file descriptor.
316  */
317 int
318 w32_close_handle(int fd)
319 {
320     int result;
321
322     result = CloseHandle((HANDLE)fd);
323
324     if (!result)
325         errno = GetLastError();
326     return result;
327 }
328 #endif /* _WIN32 */