(w32_getpw, w32_socket, w32_connect, w32_recv, w32_send,
w32_writev_socket, w32_close_socket, getpass, w32_openfd, w32_openhandle, w32_readv_handle, w32_close_handle, sysdep_init, sysdep_stdin_init, w32_select, w32_signal_handler, sigaction, stdin_read_thread, w32_ring_from_file_to_bounce_buf) [_WIN32]: New w32 equivalent functions for POSIX functions. (recvline, sendcmd, tcp_connect, hostconnect, getpass, main, intr, play, ring_to_file, ring_from_file, doexecute, doredir) [_WIN32]: Use new WIN32 equivalent functions. (main) [_WIN32]: Add sysdep_init() to support system dependent initialization for equivalence functions. (play) [_WIN32]: Add sysdef_stdin_init() to support system dependent initialization for reading stdin. (recv_input, play) [_WIN32]: Replace the calls to ring_to_file() and select() with WIN32 specific enhanced versions. Makefile.in: update dependencies with new files. Make.mk: Add using of getopt.c and getopt.h from src/lib/w32 directory. Add getopt.c and getopt.h to tar for client.
This commit is contained in:
parent
006c4bcce4
commit
f082ef9fa6
12 changed files with 750 additions and 110 deletions
3
Make.mk
3
Make.mk
|
@ -261,7 +261,7 @@ info.html/%.html: info/%.t
|
||||||
$(server): $(filter src/server/% src/lib/as/% src/lib/commands/% src/lib/player/% src/lib/subs/% src/lib/update/%, $(obj)) $(empth_obj) $(libs) $(empth_lib)
|
$(server): $(filter src/server/% src/lib/as/% src/lib/commands/% src/lib/player/% src/lib/subs/% src/lib/update/%, $(obj)) $(empth_obj) $(libs) $(empth_lib)
|
||||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
||||||
|
|
||||||
$(client): $(filter src/client/%, $(obj)) src/lib/global/version.o
|
$(client): $(filter src/client/%, $(obj)) src/lib/global/version.o src/lib/w32/getopt.o
|
||||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
||||||
|
|
||||||
$(util): $(libs)
|
$(util): $(libs)
|
||||||
|
@ -332,6 +332,7 @@ dist-client: $(cli_distgen)
|
||||||
$(notdir $(filter src/client/%, $(src)) $(cli_distgen)) \
|
$(notdir $(filter src/client/%, $(src)) $(cli_distgen)) \
|
||||||
-C $(srcdir)/include proto.h version.h \
|
-C $(srcdir)/include proto.h version.h \
|
||||||
-C $(srcdir)/src/lib/global version.c \
|
-C $(srcdir)/src/lib/global version.c \
|
||||||
|
-C $(srcdir)/src/lib/w32 getopt.h getopt.c \
|
||||||
-C $(srcdir)/man empire.6 \
|
-C $(srcdir)/man empire.6 \
|
||||||
-C $(srcdir) COPYING INSTALL install-sh
|
-C $(srcdir) COPYING INSTALL install-sh
|
||||||
|
|
||||||
|
|
|
@ -79,15 +79,16 @@ uninstall:
|
||||||
rm $(mandir)/man6/empire.6
|
rm $(mandir)/man6/empire.6
|
||||||
|
|
||||||
# FIXME generate from .d
|
# FIXME generate from .d
|
||||||
expect.$O: misc.h
|
expect.$O: misc.h sysdep_w32.h
|
||||||
host.$O: misc.h
|
host.$O: misc.h sysdep_w32.h
|
||||||
linebuf.$O: linebuf.h
|
linebuf.$O: linebuf.h
|
||||||
login.$O: misc.h proto.h
|
login.$O: misc.h proto.h sysdep_w32.h
|
||||||
main.$O: misc.h version.h
|
main.$O: misc.h version.h sysdep_w32.h
|
||||||
play.$O: linebuf.h misc.h proto.h ringbuf.h secure.h
|
play.$O: linebuf.h misc.h proto.h ringbuf.h secure.h sysdep_w32.h
|
||||||
ringbuf.$O: ringbuf.h
|
ringbuf.$O: ringbuf.h
|
||||||
secure.$O: ringbuf.h secure.h
|
secure.$O: ringbuf.h secure.h
|
||||||
servcmd.$O: misc.h proto.h secure.h
|
servcmd.$O: misc.h proto.h secure.h sysdep_w32.h
|
||||||
termlib.$O: misc.h
|
sysdep_w32.$O: misc.h sysdep_w32.h
|
||||||
|
termlib.$O: misc.h sysdep_w32.h
|
||||||
version.$O: version.h
|
version.$O: version.h
|
||||||
$(obj): config.h
|
$(obj): config.h
|
||||||
|
|
|
@ -44,6 +44,15 @@
|
||||||
#endif
|
#endif
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define recv(sock, buffer, buf_size, flags) \
|
||||||
|
w32_recv((sock), (buffer), (buf_size), (flags))
|
||||||
|
#define read(sock, buffer, buf_size) \
|
||||||
|
w32_recv((sock), (buffer), (buf_size), 0)
|
||||||
|
#define write(sock, buffer, buf_size) \
|
||||||
|
w32_send((sock), (buffer), (buf_size), 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
recvline(int s, char *buf)
|
recvline(int s, char *buf)
|
||||||
{
|
{
|
||||||
|
@ -55,15 +64,10 @@ recvline(int s, char *buf)
|
||||||
int cc;
|
int cc;
|
||||||
|
|
||||||
size = 1024;
|
size = 1024;
|
||||||
#ifndef _WIN32
|
|
||||||
(void)alarm(30);
|
(void)alarm(30);
|
||||||
#endif
|
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
n = recv(s, ptr, size, MSG_PEEK);
|
n = recv(s, ptr, size, MSG_PEEK);
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
#ifdef _WIN32
|
|
||||||
errno = WSAGetLastError();
|
|
||||||
#endif
|
|
||||||
perror("recv");
|
perror("recv");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -71,15 +75,8 @@ recvline(int s, char *buf)
|
||||||
buf[n] = '\0';
|
buf[n] = '\0';
|
||||||
if ((p = strchr(ptr, '\n')) == NULL) {
|
if ((p = strchr(ptr, '\n')) == NULL) {
|
||||||
do {
|
do {
|
||||||
#ifndef _WIN32
|
|
||||||
cc = read(s, ptr, n);
|
cc = read(s, ptr, n);
|
||||||
#else
|
|
||||||
cc = recv(s, ptr, n, 0);
|
|
||||||
#endif
|
|
||||||
if (cc < 0) {
|
if (cc < 0) {
|
||||||
#ifdef _WIN32
|
|
||||||
errno = WSAGetLastError();
|
|
||||||
#endif
|
|
||||||
perror("expect: read");
|
perror("expect: read");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -89,9 +86,6 @@ recvline(int s, char *buf)
|
||||||
}
|
}
|
||||||
ptr += n;
|
ptr += n;
|
||||||
if ((n = recv(s, ptr, size, MSG_PEEK)) <= 0) {
|
if ((n = recv(s, ptr, size, MSG_PEEK)) <= 0) {
|
||||||
#ifdef _WIN32
|
|
||||||
errno = WSAGetLastError();
|
|
||||||
#endif
|
|
||||||
perror("recv");
|
perror("recv");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -102,15 +96,8 @@ recvline(int s, char *buf)
|
||||||
*p = 0;
|
*p = 0;
|
||||||
} else
|
} else
|
||||||
newline = 1 + p - ptr;
|
newline = 1 + p - ptr;
|
||||||
#ifndef _WIN32
|
|
||||||
cc = read(s, buf, newline);
|
cc = read(s, buf, newline);
|
||||||
#else
|
|
||||||
cc = recv(s, buf, newline, 0);
|
|
||||||
#endif
|
|
||||||
if (cc < 0) {
|
if (cc < 0) {
|
||||||
#ifdef _WIN32
|
|
||||||
errno = WSAGetLastError();
|
|
||||||
#endif
|
|
||||||
perror("expect: read #2");
|
perror("expect: read #2");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -120,9 +107,7 @@ recvline(int s, char *buf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
buf[newline] = '\0';
|
buf[newline] = '\0';
|
||||||
#ifndef _WIN32
|
|
||||||
(void)alarm(0);
|
(void)alarm(0);
|
||||||
#endif
|
|
||||||
if (!isxdigit(buf[0]) || buf[1] != ' ') {
|
if (!isxdigit(buf[0]) || buf[1] != ' ') {
|
||||||
fprintf(stderr, "Malformed line %s\n", buf);
|
fprintf(stderr, "Malformed line %s\n", buf);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -146,15 +131,8 @@ sendcmd(int s, char *cmd, char *arg)
|
||||||
|
|
||||||
(void)sprintf(buf, "%s %s\n", cmd, arg != NULL ? arg : "");
|
(void)sprintf(buf, "%s %s\n", cmd, arg != NULL ? arg : "");
|
||||||
len = strlen(buf);
|
len = strlen(buf);
|
||||||
#ifndef _WIN32
|
|
||||||
cc = write(s, buf, len);
|
cc = write(s, buf, len);
|
||||||
#else
|
|
||||||
cc = send(s, buf, len, 0);
|
|
||||||
#endif
|
|
||||||
if (cc < 0) {
|
if (cc < 0) {
|
||||||
#ifdef _WIN32
|
|
||||||
errno = WSAGetLastError();
|
|
||||||
#endif
|
|
||||||
perror("sendcmd: write");
|
perror("sendcmd: write");
|
||||||
}
|
}
|
||||||
if (cc != len) {
|
if (cc != len) {
|
||||||
|
|
|
@ -48,8 +48,7 @@
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#else
|
#else
|
||||||
#include <winsock2.h>
|
#define close(fd) w32_close_socket((fd))
|
||||||
#include <ws2tcpip.h>
|
|
||||||
#endif
|
#endif
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
|
@ -83,11 +82,7 @@ tcp_connect(char *host, char *serv)
|
||||||
|
|
||||||
if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
|
if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
|
||||||
break; /* success */
|
break; /* success */
|
||||||
#ifdef _WIN32
|
|
||||||
closesocket(sockfd); /* ignore this one */
|
|
||||||
#else
|
|
||||||
close(sockfd); /* ignore this one */
|
close(sockfd); /* ignore this one */
|
||||||
#endif
|
|
||||||
} while ((res = res->ai_next) != NULL);
|
} while ((res = res->ai_next) != NULL);
|
||||||
|
|
||||||
if (res == NULL) { /* errno set from final connect() */
|
if (res == NULL) { /* errno set from final connect() */
|
||||||
|
@ -147,19 +142,11 @@ hostconnect(struct sockaddr_in *addr)
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (s < 0) {
|
if (s < 0) {
|
||||||
#ifdef _WIN32
|
|
||||||
errno = WSAGetLastError();
|
|
||||||
#endif
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
addr->sin_family = AF_INET;
|
addr->sin_family = AF_INET;
|
||||||
if (connect(s, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
|
if (connect(s, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
|
||||||
#ifdef _WIN32
|
|
||||||
errno = WSAGetLastError();
|
|
||||||
(void)closesocket(s);
|
|
||||||
#else
|
|
||||||
(void)close(s);
|
(void)close(s);
|
||||||
#endif
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
|
|
@ -89,21 +89,9 @@ login(int s, char *uname, char *cname, char *cpass,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (cpass == NULL) {
|
if (cpass == NULL) {
|
||||||
#ifndef _WIN32
|
|
||||||
cpass = getpass("Your name? ");
|
cpass = getpass("Your name? ");
|
||||||
if (cpass == NULL || *cpass == 0)
|
if (cpass == NULL || *cpass == 0)
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
|
||||||
printf("Note: This is echoed to the screen\n");
|
|
||||||
printf("Your name? ");
|
|
||||||
fflush(stdout);
|
|
||||||
cpass = fgets(tmp, sizeof(tmp), stdin);
|
|
||||||
if (cpass == NULL || *cpass == 0)
|
|
||||||
return 0;
|
|
||||||
len = strlen(cpass);
|
|
||||||
if (cname[len-1] == '\n')
|
|
||||||
cname[len-1] = 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
(void)printf("\n");
|
(void)printf("\n");
|
||||||
(void)sendcmd(s, "pass", cpass);
|
(void)sendcmd(s, "pass", cpass);
|
||||||
|
|
|
@ -36,12 +36,21 @@
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define getuid() 0
|
||||||
|
#define getpwuid(uid) ((uid), w32_getpw())
|
||||||
|
#else
|
||||||
|
#define sysdep_init() ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_usage(char *program_name)
|
print_usage(char *program_name)
|
||||||
{
|
{
|
||||||
|
@ -68,21 +77,6 @@ main(int argc, char **argv)
|
||||||
char *host;
|
char *host;
|
||||||
char *port;
|
char *port;
|
||||||
int sock;
|
int sock;
|
||||||
#ifdef _WIN32
|
|
||||||
char unamebuf[128];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
/*
|
|
||||||
* stdout is unbuffered under Windows if connected to a character
|
|
||||||
* device, and putchar() screws up when printing multibyte strings
|
|
||||||
* bytewise to an unbuffered stream. Switch stdout to line-
|
|
||||||
* buffered mode. Unfortunately, ISO C allows implementations to
|
|
||||||
* screw that up, and of course Windows does. Manual flushing
|
|
||||||
* after each prompt is required.
|
|
||||||
*/
|
|
||||||
setvbuf(stdout, NULL, _IOLBF, 4096);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "2:kuhv")) != EOF) {
|
while ((opt = getopt(argc, argv, "2:kuhv")) != EOF) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
@ -124,7 +118,6 @@ main(int argc, char **argv)
|
||||||
host = empirehost;
|
host = empirehost;
|
||||||
uname = getenv("LOGNAME");
|
uname = getenv("LOGNAME");
|
||||||
if (uname == NULL) {
|
if (uname == NULL) {
|
||||||
#ifndef _WIN32
|
|
||||||
struct passwd *pwd;
|
struct passwd *pwd;
|
||||||
|
|
||||||
pwd = getpwuid(getuid());
|
pwd = getpwuid(getuid());
|
||||||
|
@ -133,17 +126,6 @@ main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
uname = pwd->pw_name;
|
uname = pwd->pw_name;
|
||||||
#else
|
|
||||||
DWORD unamesize;
|
|
||||||
|
|
||||||
unamesize = sizeof(unamebuf);
|
|
||||||
if (GetUserName(unamebuf, &unamesize)) {
|
|
||||||
uname = unamebuf;
|
|
||||||
if ((unamesize <= 0 ) || (strlen(uname) <= 0))
|
|
||||||
uname = "nobody";
|
|
||||||
} else
|
|
||||||
uname = "nobody";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getsose();
|
getsose();
|
||||||
|
@ -152,13 +134,7 @@ main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
sysdep_init();
|
||||||
err = WSAStartup(MAKEWORD(2, 0), &WsaData);
|
|
||||||
if (err != 0) {
|
|
||||||
printf("WSAStartup Failed, error code %d\n", err);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sock = tcp_connect(host, port);
|
sock = tcp_connect(host, port);
|
||||||
|
|
||||||
|
|
|
@ -36,10 +36,11 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include "sysdep_w32.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
|
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
|
||||||
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
extern char empirehost[];
|
extern char empirehost[];
|
||||||
extern char empireport[];
|
extern char empireport[];
|
||||||
|
@ -50,13 +51,7 @@ extern FILE *auxfp;
|
||||||
extern char *SO;
|
extern char *SO;
|
||||||
extern char *SE;
|
extern char *SE;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifndef _WIN32
|
||||||
#define getsose() ((void)0)
|
|
||||||
#define putso() ((void)0)
|
|
||||||
#define putse() ((void)0)
|
|
||||||
#define pclose _pclose
|
|
||||||
#define popen _popen
|
|
||||||
#else
|
|
||||||
void getsose(void);
|
void getsose(void);
|
||||||
void putso(void);
|
void putso(void);
|
||||||
void putse(void);
|
void putse(void);
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
*
|
*
|
||||||
* Known contributors to this file:
|
* Known contributors to this file:
|
||||||
* Markus Armbruster, 2007
|
* Markus Armbruster, 2007
|
||||||
|
* Ron Koenderink, 2007
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
@ -38,15 +39,254 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#ifndef _WIN32
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
#include "linebuf.h"
|
#include "linebuf.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
#include "ringbuf.h"
|
#include "ringbuf.h"
|
||||||
#include "secure.h"
|
#include "secure.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static CRITICAL_SECTION signal_critical_section;
|
||||||
|
static LPCRITICAL_SECTION signal_critical_section_ptr = NULL;
|
||||||
|
|
||||||
|
static unsigned char bounce_buf[RING_SIZE];
|
||||||
|
/*
|
||||||
|
* Set bounce_empty to indicate bounce_buf is available for the stdin thread
|
||||||
|
* to use.
|
||||||
|
*/
|
||||||
|
static HANDLE bounce_empty;
|
||||||
|
/*
|
||||||
|
* Set bounce_full to indicate bounce_buf is contains data from the
|
||||||
|
* stdin thread and is available for recv_input
|
||||||
|
*/
|
||||||
|
static HANDLE bounce_full;
|
||||||
|
/* Ctrl-C (SIGINT) was detected, generate EINTR for the w32_select() */
|
||||||
|
static HANDLE ctrl_c_event;
|
||||||
|
static int bounce_status, bounce_error;
|
||||||
|
|
||||||
|
#define SIGPIPE -1
|
||||||
|
static void (*ctrl_handler)(int sig) = { SIG_DFL };
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ctrl-C handler for emulating the SIGINT in WIN32
|
||||||
|
*/
|
||||||
|
static BOOL WINAPI
|
||||||
|
w32_signal_handler(DWORD ctrl_type)
|
||||||
|
{
|
||||||
|
if (ctrl_type == CTRL_C_EVENT) {
|
||||||
|
EnterCriticalSection(signal_critical_section_ptr);
|
||||||
|
if (ctrl_handler != SIG_DFL) {
|
||||||
|
ctrl_handler(SIGINT);
|
||||||
|
LeaveCriticalSection(signal_critical_section_ptr);
|
||||||
|
SetEvent(ctrl_c_event);
|
||||||
|
return TRUE;
|
||||||
|
} else
|
||||||
|
LeaveCriticalSection(signal_critical_section_ptr);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WIN32 equivalent for sigaction supports the following:
|
||||||
|
* set handler for SIGINT using WIN32 Ctrl-C handler
|
||||||
|
* reset handler SIGINT to SIG_DFL
|
||||||
|
* ignore SIGPIPE
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
sigaction(int signal, struct sigaction *action, struct sigaction *oaction)
|
||||||
|
{
|
||||||
|
assert(!oaction);
|
||||||
|
assert(action);
|
||||||
|
|
||||||
|
if (signal == SIGPIPE)
|
||||||
|
assert(action->sa_handler == SIG_IGN);
|
||||||
|
else {
|
||||||
|
assert(signal == SIGINT && action->sa_handler != SIG_IGN);
|
||||||
|
if (ctrl_handler == action->sa_handler)
|
||||||
|
return 0;
|
||||||
|
if (signal_critical_section_ptr == NULL) {
|
||||||
|
signal_critical_section_ptr = &signal_critical_section;
|
||||||
|
InitializeCriticalSection(signal_critical_section_ptr);
|
||||||
|
}
|
||||||
|
EnterCriticalSection(signal_critical_section_ptr);
|
||||||
|
if (!SetConsoleCtrlHandler(w32_signal_handler,
|
||||||
|
action->sa_handler != SIG_DFL)) {
|
||||||
|
errno = GetLastError();
|
||||||
|
LeaveCriticalSection(signal_critical_section_ptr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ctrl_handler = action->sa_handler;
|
||||||
|
LeaveCriticalSection(signal_critical_section_ptr);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the stdin in WIN32 environment
|
||||||
|
* WIN32 does not support select type function on console input
|
||||||
|
* so the client uses a separate thread to read input
|
||||||
|
*/
|
||||||
|
static DWORD WINAPI
|
||||||
|
stdin_read_thread(LPVOID lpParam)
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
if (WaitForSingleObject(bounce_empty, INFINITE) != WAIT_OBJECT_0)
|
||||||
|
break;
|
||||||
|
bounce_status = _read(0, bounce_buf, sizeof(bounce_buf));
|
||||||
|
bounce_error = errno;
|
||||||
|
if (bounce_status == 0) {
|
||||||
|
if (_isatty(0)) {
|
||||||
|
SetEvent(bounce_empty);
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SetEvent(bounce_full);
|
||||||
|
}
|
||||||
|
SetEvent(bounce_full);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize and start the stdin reading thread for WIN32
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sysdep_stdin_init()
|
||||||
|
{
|
||||||
|
bounce_empty = CreateEvent(NULL, FALSE, TRUE, "bounce_empty");
|
||||||
|
bounce_full = CreateEvent(NULL, TRUE, FALSE, "bounce_full");
|
||||||
|
ctrl_c_event = CreateEvent(NULL, FALSE, FALSE, "Ctrl_C");
|
||||||
|
CreateThread(NULL, 0, stdin_read_thread, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function uses to WaitForMultipleObjects to wait for both
|
||||||
|
* stdin and socket reading or writing.
|
||||||
|
* Stdin is treated special in WIN32. Waiting for stdin is done
|
||||||
|
* via a bounce_full event which is set in the stdin thread.
|
||||||
|
* Execute command file reading is done via handle. Execute
|
||||||
|
* command is read via CreateFile/ReadFile instead open/read
|
||||||
|
* because a file descriptor is not waitable.
|
||||||
|
* WaitForMultipleObjects will only respond with one object
|
||||||
|
* so an additonal select is also done to determine
|
||||||
|
* which individual events are active for the sock.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
w32_select(int nfds, fd_set *rdfd, fd_set *wrfd, fd_set *errfd, struct timeval* time)
|
||||||
|
{
|
||||||
|
HANDLE handles[3];
|
||||||
|
SOCKET sock;
|
||||||
|
int result, s_result, num_handles = 0;
|
||||||
|
struct timeval tv_time = {0, 0};
|
||||||
|
fd_set rdfd2;
|
||||||
|
|
||||||
|
if (rdfd->fd_count > 1) {
|
||||||
|
sock = rdfd->fd_array[1];
|
||||||
|
if (rdfd->fd_array[0])
|
||||||
|
handles[num_handles++] = (HANDLE)rdfd->fd_array[0];
|
||||||
|
else {
|
||||||
|
handles[num_handles++] = ctrl_c_event;
|
||||||
|
handles[num_handles++] = bounce_full;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(rdfd->fd_count == 1);
|
||||||
|
sock = rdfd->fd_array[0];
|
||||||
|
}
|
||||||
|
assert(wrfd->fd_count == 0 ||
|
||||||
|
(wrfd->fd_count == 1 && wrfd->fd_array[0] == sock));
|
||||||
|
/* always wait on the socket */
|
||||||
|
handles[num_handles++] = WSACreateEvent();
|
||||||
|
|
||||||
|
if (wrfd->fd_count > 0)
|
||||||
|
WSAEventSelect(sock, handles[num_handles - 1],
|
||||||
|
FD_READ | FD_WRITE | FD_CLOSE);
|
||||||
|
else
|
||||||
|
WSAEventSelect(sock, handles[num_handles - 1],
|
||||||
|
FD_READ | FD_CLOSE);
|
||||||
|
|
||||||
|
result = WaitForMultipleObjects(num_handles, handles, 0, INFINITE);
|
||||||
|
if (result < 0) {
|
||||||
|
errno = GetLastError();
|
||||||
|
WSACloseEvent(handles[num_handles - 1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
WSACloseEvent(handles[num_handles - 1]);
|
||||||
|
|
||||||
|
if (num_handles == 3 && result == WAIT_OBJECT_0) {
|
||||||
|
errno = EINTR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&rdfd2);
|
||||||
|
FD_SET(sock, &rdfd2);
|
||||||
|
s_result = select(sock + 1, &rdfd2, wrfd, NULL, &tv_time);
|
||||||
|
|
||||||
|
if (s_result < 0) {
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
return s_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rdfd = rdfd2;
|
||||||
|
if (num_handles == 3 && result == WAIT_OBJECT_0 + 1) {
|
||||||
|
FD_SET((SOCKET)0, rdfd);
|
||||||
|
s_result++;
|
||||||
|
}
|
||||||
|
if (num_handles == 2 && result == WAIT_OBJECT_0) {
|
||||||
|
FD_SET((SOCKET)handles[0], rdfd);
|
||||||
|
s_result++;
|
||||||
|
}
|
||||||
|
return s_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read input from the user either stdin or from file.
|
||||||
|
* For stdin, read from bounce_buf which filled by the stdin thread
|
||||||
|
* otherwise use the regular ring_from_file.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
w32_ring_from_file_or_bounce_buf(struct ring *r, int fd)
|
||||||
|
{
|
||||||
|
int i, res;
|
||||||
|
|
||||||
|
if (fd)
|
||||||
|
return ring_from_file(r, fd);
|
||||||
|
|
||||||
|
if (bounce_status < 0) {
|
||||||
|
errno = bounce_error;
|
||||||
|
res = bounce_status;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < bounce_status; i++) {
|
||||||
|
if (ring_putc(r, bounce_buf[i]) == EOF) {
|
||||||
|
/* more work to do, hold on to bounce_buf */
|
||||||
|
memmove(bounce_buf, bounce_buf + i, bounce_status - i);
|
||||||
|
bounce_status -= i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetEvent(bounce_full);
|
||||||
|
SetEvent(bounce_empty);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#define ring_from_file w32_ring_from_file_or_bounce_buf
|
||||||
|
#define close(fd) w32_close_handle((fd))
|
||||||
|
#define read(sock, buffer, buf_size) \
|
||||||
|
w32_recv((sock), (buffer), (buf_size), 0)
|
||||||
|
#define select(nfds, rd, wr, error, time) \
|
||||||
|
w32_select((nfds), (rd), (wr), (error), (time))
|
||||||
|
#else
|
||||||
|
#define sysdep_stdin_init() ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define EOF_COOKIE "ctld\n"
|
#define EOF_COOKIE "ctld\n"
|
||||||
#define INTR_COOKIE "\naborted\n"
|
#define INTR_COOKIE "\naborted\n"
|
||||||
|
|
||||||
|
@ -197,9 +437,6 @@ static void
|
||||||
intr(int sig)
|
intr(int sig)
|
||||||
{
|
{
|
||||||
send_intr = 1;
|
send_intr = 1;
|
||||||
#ifdef _WIN32
|
|
||||||
signal(SIGINT, intr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -231,6 +468,7 @@ play(int sock)
|
||||||
ring_init(&inbuf);
|
ring_init(&inbuf);
|
||||||
eof_fd0 = send_eof = send_intr = 0;
|
eof_fd0 = send_eof = send_intr = 0;
|
||||||
input_fd = 0;
|
input_fd = 0;
|
||||||
|
sysdep_stdin_init(&eof_fd0, &inbuf);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
FD_ZERO(&rdfd);
|
FD_ZERO(&rdfd);
|
||||||
|
|
|
@ -36,8 +36,16 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#ifndef _WIN32
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#define readv(fd, iov, iovcnt) \
|
||||||
|
w32_readv_handle((fd), (iov), (iovcnt))
|
||||||
|
#define writev(fd, iov, iovcnt) \
|
||||||
|
w32_writev_socket((fd), (iov), (iovcnt))
|
||||||
|
#endif
|
||||||
|
#include "misc.h"
|
||||||
#include "ringbuf.h"
|
#include "ringbuf.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -46,6 +46,13 @@
|
||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
#include "secure.h"
|
#include "secure.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define open(filename, flags, ...) \
|
||||||
|
((flags & O_CREAT) \
|
||||||
|
? w32_openfd((filename), (flags), ## __VA_ARGS__) \
|
||||||
|
: w32_openhandle((filename), (flags)))
|
||||||
|
#endif
|
||||||
|
|
||||||
int eight_bit_clean;
|
int eight_bit_clean;
|
||||||
FILE *auxfp;
|
FILE *auxfp;
|
||||||
|
|
||||||
|
|
366
src/client/sysdep_w32.c
Normal file
366
src/client/sysdep_w32.c
Normal file
|
@ -0,0 +1,366 @@
|
||||||
|
/*
|
||||||
|
* Empire - A multi-player, client/server Internet based war game.
|
||||||
|
* Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
|
||||||
|
* Ken Stevens, Steve McClure
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* See files README, COPYING and CREDITS in the root of the source
|
||||||
|
* tree for related information and legal notices. It is expected
|
||||||
|
* that future projects/authors will amend these files as needed.
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* sysdep_w32.c: system dependent functions for WIN32 environments
|
||||||
|
*
|
||||||
|
* Known contributors to this file:
|
||||||
|
* Ron Koenderink, 2007
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "misc.h"
|
||||||
|
#include "linebuf.h"
|
||||||
|
#include "ringbuf.h"
|
||||||
|
#include "secure.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ignore alarm for WIN32 client
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
alarm(int time)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get user name in the WIN32 environment
|
||||||
|
*/
|
||||||
|
struct passwd *
|
||||||
|
w32_getpw(void)
|
||||||
|
{
|
||||||
|
static char unamebuf[128];
|
||||||
|
static struct passwd pwd;
|
||||||
|
long unamesize;
|
||||||
|
|
||||||
|
unamesize = sizeof(unamebuf);
|
||||||
|
if (GetUserName(unamebuf, &unamesize)) {
|
||||||
|
pwd.pw_name = unamebuf;
|
||||||
|
if ((unamesize <= 0 ) || (strlen(unamebuf) <= 0))
|
||||||
|
pwd.pw_name = "nobody";
|
||||||
|
} else
|
||||||
|
pwd.pw_name = "nobody";
|
||||||
|
return &pwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the WIN32 socket library and
|
||||||
|
* set up stdout to work around bugs
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sysdep_init(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
WSADATA WsaData;
|
||||||
|
/*
|
||||||
|
* stdout is unbuffered under Windows if connected to a character
|
||||||
|
* device, and putchar() screws up when printing multibyte strings
|
||||||
|
* bytewise to an unbuffered stream. Switch stdout to line-
|
||||||
|
* buffered mode. Unfortunately, ISO C allows implementations to
|
||||||
|
* screw that up, and of course Windows does. Manual flushing
|
||||||
|
* after each prompt is required.
|
||||||
|
*/
|
||||||
|
setvbuf(stdout, NULL, _IOLBF, 4096);
|
||||||
|
err = WSAStartup(MAKEWORD(2, 0), &WsaData);
|
||||||
|
if (err != 0) {
|
||||||
|
printf("WSAStartup Failed, error code %d\n", err);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* POSIX compatible socket() replacement
|
||||||
|
*/
|
||||||
|
#undef socket
|
||||||
|
int
|
||||||
|
w32_socket(int family, int sock_type, int protocol)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = socket(family, sock_type, protocol);
|
||||||
|
if (result == INVALID_SOCKET) {
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* POSIX compatible connect() replacement
|
||||||
|
*/
|
||||||
|
#undef connect
|
||||||
|
int
|
||||||
|
w32_connect(int sock, struct sockaddr *addr, int addrlen)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = connect(sock, addr, addrlen);
|
||||||
|
if (result == SOCKET_ERROR) {
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* POSIX compatible recv() replacement
|
||||||
|
*/
|
||||||
|
#undef recv
|
||||||
|
int
|
||||||
|
w32_recv(int socket, char *buffer, size_t buf_size, int flags)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = recv(socket, buffer, buf_size, flags);
|
||||||
|
if (result == SOCKET_ERROR) {
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* POSIX compatible writev() replacement specialized to sockets
|
||||||
|
* Modelled after the GNU's libc/sysdeps/posix/writev.c
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
w32_writev_socket(int fd, const struct iovec *iov, int iovcnt)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char *buffer, *buffer_location;
|
||||||
|
size_t total_bytes = 0;
|
||||||
|
int bytes_written;
|
||||||
|
|
||||||
|
for (i = 0; i < iovcnt; i++)
|
||||||
|
total_bytes += iov[i].iov_len;
|
||||||
|
|
||||||
|
buffer = malloc(total_bytes);
|
||||||
|
if (buffer == NULL && total_bytes != 0) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_location = buffer;
|
||||||
|
for (i = 0; i < iovcnt; i++) {
|
||||||
|
memcpy(buffer_location, iov[i].iov_base, iov[i].iov_len);
|
||||||
|
buffer_location += iov[i].iov_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_written = send(fd, buffer, total_bytes, 0);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
if (bytes_written == SOCKET_ERROR) {
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return bytes_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* POSIX compatible send() replacement
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
w32_send(int socket, char *buffer, size_t buf_size, int flags)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = send(socket, buffer, buf_size, flags);
|
||||||
|
if (result == SOCKET_ERROR)
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* POSIX compatible close() replacement specialized to sockets.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
w32_close_socket(int fd)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = closesocket(fd);
|
||||||
|
if (result == SOCKET_ERROR)
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WIN32 equivalent for getpass
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
getpass(char *prompt)
|
||||||
|
{
|
||||||
|
static char tmp[128];
|
||||||
|
int len;
|
||||||
|
char *cpass;
|
||||||
|
DWORD mode;
|
||||||
|
HANDLE input_handle = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
|
||||||
|
if (GetConsoleMode(input_handle, &mode))
|
||||||
|
SetConsoleMode(input_handle, mode & ~ENABLE_ECHO_INPUT);
|
||||||
|
else
|
||||||
|
printf("Note: This is echoed to the screen\n");
|
||||||
|
printf("%s", prompt);
|
||||||
|
fflush(stdout);
|
||||||
|
cpass = fgets(tmp, sizeof(tmp), stdin);
|
||||||
|
if (GetConsoleMode(input_handle, &mode))
|
||||||
|
SetConsoleMode(input_handle, mode | ENABLE_ECHO_INPUT);
|
||||||
|
if (cpass == NULL)
|
||||||
|
return NULL;
|
||||||
|
len = strlen(cpass);
|
||||||
|
if (tmp[len - 1] == '\n')
|
||||||
|
tmp[len - 1] = 0;
|
||||||
|
return cpass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* POSIX compatible open() replacement
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
w32_openfd(const char *fname, int oflag, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int pmode = 0;
|
||||||
|
int fd;
|
||||||
|
int create_permission = 0;
|
||||||
|
|
||||||
|
if (oflag & O_CREAT) {
|
||||||
|
va_start(ap, oflag);
|
||||||
|
pmode = va_arg(ap, int);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (pmode & 0400)
|
||||||
|
create_permission |= _S_IREAD;
|
||||||
|
if (pmode & 0200)
|
||||||
|
create_permission |= _S_IWRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = _open(fname, oflag, create_permission);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Open a file for reading, return its handle.
|
||||||
|
* This can be used in place of open() when a handle is desired for
|
||||||
|
* waiting on it with WaitForMultipleObjects() or similar.
|
||||||
|
* Ensure the handle is not zero in order to prevent a problem
|
||||||
|
* input_fd.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
w32_openhandle(const char *fname, int oflag)
|
||||||
|
{
|
||||||
|
HANDLE handle;
|
||||||
|
|
||||||
|
handle = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
|
||||||
|
if (handle == INVALID_HANDLE_VALUE) {
|
||||||
|
errno = GetLastError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (handle == 0) {
|
||||||
|
HANDLE dup_handle;
|
||||||
|
if (!DuplicateHandle(GetCurrentProcess(), handle,
|
||||||
|
GetCurrentProcess(), &dup_handle,
|
||||||
|
0, FALSE, DUPLICATE_SAME_ACCESS)) {
|
||||||
|
errno = GetLastError();
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
CloseHandle(handle);
|
||||||
|
handle = dup_handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (int)handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* POSIX compatible readv() replacement specialized to files.
|
||||||
|
* Modelled after the GNU's libc/sysdeps/posix/readv.c
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
w32_readv_handle(int fd, const struct iovec *iov, int iovcnt)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char *buffer, *buffer_location;
|
||||||
|
size_t total_bytes = 0;
|
||||||
|
DWORD bytes_read;
|
||||||
|
size_t bytes_left;
|
||||||
|
|
||||||
|
for (i = 0; i < iovcnt; i++) {
|
||||||
|
total_bytes += iov[i].iov_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = malloc(total_bytes);
|
||||||
|
if (buffer == NULL && total_bytes != 0) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ReadFile((HANDLE)fd, buffer, total_bytes, &bytes_read, NULL)) {
|
||||||
|
free(buffer);
|
||||||
|
errno = GetLastError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_left = bytes_read;
|
||||||
|
buffer_location = buffer;
|
||||||
|
for (i = 0; i < iovcnt; i++) {
|
||||||
|
size_t copy = MIN(iov[i].iov_len, bytes_left);
|
||||||
|
|
||||||
|
memcpy(iov[i].iov_base, buffer_location, copy);
|
||||||
|
|
||||||
|
buffer_location += copy;
|
||||||
|
bytes_left -= copy;
|
||||||
|
if (bytes_left == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* POSIX compatible close() replacement specialized to files.
|
||||||
|
* Hack: expects a handle, cannot be used with a file descriptor.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
w32_close_handle(int fd)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = CloseHandle((HANDLE)fd);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
errno = GetLastError();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif /* _WIN32 */
|
95
src/client/sysdep_w32.h
Normal file
95
src/client/sysdep_w32.h
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Empire - A multi-player, client/server Internet based war game.
|
||||||
|
* Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
|
||||||
|
* Ken Stevens, Steve McClure
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* See files README, COPYING and CREDITS in the root of the source
|
||||||
|
* tree for related information and legal notices. It is expected
|
||||||
|
* that future projects/authors will amend these files as needed.
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* sysdep_w32.h: system dependent support for WIN32 environments
|
||||||
|
*
|
||||||
|
* Known contributors to this file:
|
||||||
|
* Ron Koenderink, 2007
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SYSDEF_W32_H
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
extern int getopt(int, char * const[], const char *);
|
||||||
|
extern char *optarg;
|
||||||
|
extern int optind, opterr, optopt;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
typedef int __w64 ssize_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct passwd {
|
||||||
|
char *pw_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct iovec {
|
||||||
|
void *iov_base;
|
||||||
|
size_t iov_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sigaction {
|
||||||
|
int sa_flags;
|
||||||
|
void (*sa_handler)(int sig);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int w32_recv(int socket, char *buffer,
|
||||||
|
size_t buf_size, int flags);
|
||||||
|
extern int w32_send(int socket, char *buffer,
|
||||||
|
size_t buf_size, int flags);
|
||||||
|
extern int w32_close_socket(int fd);
|
||||||
|
extern int w32_socket(int family, int sock_type, int protocol);
|
||||||
|
extern int w32_connect(int sock, struct sockaddr *addr, int addrlen);
|
||||||
|
extern int w32_close_handle(int fd);
|
||||||
|
extern ssize_t w32_readv_handle(int fd, const struct iovec *iov,
|
||||||
|
int iovcnt);
|
||||||
|
extern ssize_t w32_writev_socket(int fd, const struct iovec *iov,
|
||||||
|
int iovcnt);
|
||||||
|
extern int w32_createfd(const char *fname, int oflag, ...);
|
||||||
|
extern int w32_openhandle(const char *fname, int oflag);
|
||||||
|
|
||||||
|
extern int alarm(int time);
|
||||||
|
extern struct passwd *w32_getpw(void);
|
||||||
|
extern char *getpass(char *prompt);
|
||||||
|
extern void sysdep_init(void);
|
||||||
|
|
||||||
|
#define recv(sock, buffer, buf_size, flags) \
|
||||||
|
w32_recv((sock), (buffer), (buf_size), (flags))
|
||||||
|
#define socket(family, sock_type, protocol) \
|
||||||
|
w32_socket((family), (sock_type), (protocol))
|
||||||
|
#define connect(sock, addr, addrlen) \
|
||||||
|
w32_connect((sock), (addr), (addrlen))
|
||||||
|
|
||||||
|
#define pclose _pclose
|
||||||
|
#define popen _popen
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#define getsose() ((void)0)
|
||||||
|
#define putso() ((void)0)
|
||||||
|
#define putse() ((void)0)
|
||||||
|
#endif /* sysdef_w32.h */
|
Loading…
Add table
Add a link
Reference in a new issue