mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* io.c (pipe_open): win32 bidirectional pipe support.
* win32/win32.[ch] (rb_w32_pipe_exec): ditto. * win32/win32.[ch] (socketpair): new function. POSIX socketpair emulation. * win32/win32.c (socketpair_internal): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7493 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
6100eced2e
commit
c3ce319d7d
4 changed files with 191 additions and 77 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
Wed Dec 08 00:44:31 2004 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||||
|
|
||||||
|
* io.c (pipe_open): win32 bidirectional pipe support.
|
||||||
|
|
||||||
|
* win32/win32.[ch] (rb_w32_pipe_exec): ditto.
|
||||||
|
|
||||||
|
* win32/win32.[ch] (socketpair): new function. POSIX socketpair
|
||||||
|
emulation.
|
||||||
|
|
||||||
|
* win32/win32.c (socketpair_internal): ditto.
|
||||||
|
|
||||||
Wed Dec 8 00:25:07 2004 Kouhei Sutou <kou@cozmixng.org>
|
Wed Dec 8 00:25:07 2004 Kouhei Sutou <kou@cozmixng.org>
|
||||||
|
|
||||||
* test/rss/test_version.rb: added version check test.
|
* test/rss/test_version.rb: added version check test.
|
||||||
|
|
11
io.c
11
io.c
|
@ -2805,7 +2805,7 @@ pipe_open(argc, argv, mode)
|
||||||
struct popen_arg arg;
|
struct popen_arg arg;
|
||||||
volatile int doexec;
|
volatile int doexec;
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
int r, w;
|
int fd;
|
||||||
int openmode = rb_io_mode_modenum(mode);
|
int openmode = rb_io_mode_modenum(mode);
|
||||||
char *exename = NULL;
|
char *exename = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2895,7 +2895,7 @@ pipe_open(argc, argv, mode)
|
||||||
else {
|
else {
|
||||||
cmd = StringValueCStr(prog);
|
cmd = StringValueCStr(prog);
|
||||||
}
|
}
|
||||||
while ((pid = rb_w32_pipe_exec(cmd, exename, openmode, &r, &w)) == -1) {
|
while ((pid = rb_w32_pipe_exec(cmd, exename, openmode, &fd)) == -1) {
|
||||||
/* exec failed */
|
/* exec failed */
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
|
@ -2910,14 +2910,13 @@ pipe_open(argc, argv, mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((modef & FMODE_READABLE) && (modef & FMODE_WRITABLE)) {
|
if ((modef & FMODE_READABLE) && (modef & FMODE_WRITABLE)) {
|
||||||
close(w);
|
fp = rb_fdopen(fd, "r+");
|
||||||
fp = rb_fdopen(r, "r+");
|
|
||||||
}
|
}
|
||||||
else if (modef & FMODE_READABLE) {
|
else if (modef & FMODE_READABLE) {
|
||||||
fp = rb_fdopen(r, "r");
|
fp = rb_fdopen(fd, "r");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fp = rb_fdopen(w, "w");
|
fp = rb_fdopen(fd, "w");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
|
prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
|
||||||
|
|
238
win32/win32.c
238
win32/win32.c
|
@ -673,124 +673,120 @@ rb_w32_join_argv(char *cmd, char *const *argv)
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int socketpair_internal(int af, int type, int protocol, SOCKET *sv);
|
||||||
|
|
||||||
pid_t
|
pid_t
|
||||||
rb_w32_pipe_exec(const char *cmd, const char *prog, int mode,
|
rb_w32_pipe_exec(const char *cmd, const char *prog, int mode, int *pipe)
|
||||||
int *pr, int *pw)
|
|
||||||
{
|
{
|
||||||
struct ChildRecord* child;
|
struct ChildRecord* child;
|
||||||
HANDLE hReadIn, hReadOut;
|
HANDLE hOrg, hIn, hOut;
|
||||||
HANDLE hWriteIn, hWriteOut;
|
HANDLE hDupFile;
|
||||||
HANDLE hDupInFile, hDupOutFile;
|
|
||||||
HANDLE hCurProc;
|
HANDLE hCurProc;
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
BOOL fRet;
|
BOOL fRet;
|
||||||
BOOL reading, writing;
|
BOOL reading, writing;
|
||||||
|
SOCKET pair[2];
|
||||||
int fd;
|
int fd;
|
||||||
int pipemode;
|
int pipemode;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Figure out what we're doing... */
|
/* Figure out what we're doing... */
|
||||||
writing = (mode & (O_WRONLY | O_RDWR)) ? TRUE : FALSE;
|
if (mode & O_RDWR) {
|
||||||
reading = ((mode & O_RDWR) || !writing) ? TRUE : FALSE;
|
reading = writing = TRUE;
|
||||||
if (mode & O_BINARY) {
|
pipemode = _O_RDWR;
|
||||||
pipemode = O_BINARY;
|
}
|
||||||
|
else if (mode & O_WRONLY) {
|
||||||
|
reading = FALSE;
|
||||||
|
writing = TRUE;
|
||||||
|
pipemode = _O_WRONLY;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pipemode = O_TEXT;
|
reading = TRUE;
|
||||||
|
writing = FALSE;
|
||||||
|
pipemode = _O_RDONLY;
|
||||||
}
|
}
|
||||||
|
pipemode |= (mode & O_BINARY) ? O_BINARY : O_TEXT;
|
||||||
|
|
||||||
sa.nLength = sizeof (SECURITY_ATTRIBUTES);
|
sa.nLength = sizeof (SECURITY_ATTRIBUTES);
|
||||||
sa.lpSecurityDescriptor = NULL;
|
sa.lpSecurityDescriptor = NULL;
|
||||||
sa.bInheritHandle = TRUE;
|
sa.bInheritHandle = TRUE;
|
||||||
ret = -1;
|
ret = -1;
|
||||||
hWriteIn = hReadOut = NULL;
|
|
||||||
|
|
||||||
RUBY_CRITICAL(do {
|
RUBY_CRITICAL(do {
|
||||||
/* create pipe */
|
/* create pipe */
|
||||||
hCurProc = GetCurrentProcess();
|
hCurProc = GetCurrentProcess();
|
||||||
if (reading) {
|
if (reading && writing) {
|
||||||
fRet = CreatePipe(&hReadIn, &hReadOut, &sa, 2048L);
|
if (socketpair_internal(AF_INET, SOCK_STREAM, 0, pair) < 0) {
|
||||||
if (!fRet) {
|
|
||||||
errno = map_errno(GetLastError());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!DuplicateHandle(hCurProc, hReadIn, hCurProc, &hDupInFile, 0,
|
if (!DuplicateHandle(hCurProc, (HANDLE)pair[1], hCurProc,
|
||||||
FALSE, DUPLICATE_SAME_ACCESS)) {
|
&hDupFile, 0, FALSE,
|
||||||
|
DUPLICATE_SAME_ACCESS)) {
|
||||||
errno = map_errno(GetLastError());
|
errno = map_errno(GetLastError());
|
||||||
CloseHandle(hReadIn);
|
CloseHandle((HANDLE)pair[0]);
|
||||||
CloseHandle(hReadOut);
|
CloseHandle((HANDLE)pair[1]);
|
||||||
CloseHandle(hCurProc);
|
CloseHandle(hCurProc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
CloseHandle(hReadIn);
|
hOrg = hIn = hOut = (HANDLE)pair[0];
|
||||||
}
|
}
|
||||||
if (writing) {
|
else if (reading) {
|
||||||
fRet = CreatePipe(&hWriteIn, &hWriteOut, &sa, 2048L);
|
fRet = CreatePipe(&hIn, &hOut, &sa, 2048L);
|
||||||
if (!fRet) {
|
if (!fRet) {
|
||||||
errno = map_errno(GetLastError());
|
errno = map_errno(GetLastError());
|
||||||
write_pipe_failed:
|
|
||||||
if (reading) {
|
|
||||||
CloseHandle(hDupInFile);
|
|
||||||
CloseHandle(hReadOut);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!DuplicateHandle(hCurProc, hWriteOut, hCurProc, &hDupOutFile, 0,
|
if (!DuplicateHandle(hCurProc, hIn, hCurProc, &hDupFile, 0,
|
||||||
FALSE, DUPLICATE_SAME_ACCESS)) {
|
FALSE, DUPLICATE_SAME_ACCESS)) {
|
||||||
errno = map_errno(GetLastError());
|
errno = map_errno(GetLastError());
|
||||||
CloseHandle(hWriteIn);
|
CloseHandle(hIn);
|
||||||
CloseHandle(hWriteOut);
|
CloseHandle(hOut);
|
||||||
CloseHandle(hCurProc);
|
CloseHandle(hCurProc);
|
||||||
goto write_pipe_failed;
|
break;
|
||||||
}
|
}
|
||||||
CloseHandle(hWriteOut);
|
CloseHandle(hIn);
|
||||||
|
hIn = NULL;
|
||||||
|
hOrg = hOut;
|
||||||
|
}
|
||||||
|
else { /* writing */
|
||||||
|
fRet = CreatePipe(&hIn, &hOut, &sa, 2048L);
|
||||||
|
if (!fRet) {
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!DuplicateHandle(hCurProc, hOut, hCurProc, &hDupFile, 0,
|
||||||
|
FALSE, DUPLICATE_SAME_ACCESS)) {
|
||||||
|
errno = map_errno(GetLastError());
|
||||||
|
CloseHandle(hIn);
|
||||||
|
CloseHandle(hOut);
|
||||||
|
CloseHandle(hCurProc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CloseHandle(hOut);
|
||||||
|
hOut = NULL;
|
||||||
|
hOrg = hIn;
|
||||||
}
|
}
|
||||||
CloseHandle(hCurProc);
|
CloseHandle(hCurProc);
|
||||||
|
|
||||||
/* create child process */
|
/* create child process */
|
||||||
child = CreateChild(cmd, prog, &sa, hWriteIn, hReadOut, NULL);
|
child = CreateChild(cmd, prog, &sa, hIn, hOut, NULL);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
if (reading) {
|
CloseHandle(hOrg);
|
||||||
CloseHandle(hReadOut);
|
CloseHandle(hDupFile);
|
||||||
CloseHandle(hDupInFile);
|
|
||||||
}
|
|
||||||
if (writing) {
|
|
||||||
CloseHandle(hWriteIn);
|
|
||||||
CloseHandle(hDupOutFile);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* associate handle to fp */
|
/* associate handle to file descritor */
|
||||||
if (reading) {
|
*pipe = rb_w32_open_osfhandle((long)hDupFile, pipemode);
|
||||||
*pr = rb_w32_open_osfhandle((long)hDupInFile,
|
if (!(reading && writing))
|
||||||
(_O_RDONLY | pipemode));
|
CloseHandle(hOrg);
|
||||||
CloseHandle(hReadOut);
|
if (*pipe == -1) {
|
||||||
if (*pr == -1) {
|
CloseHandle(hDupFile);
|
||||||
CloseHandle(hDupInFile);
|
CloseChildHandle(child);
|
||||||
read_open_failed:
|
break;
|
||||||
if (writing) {
|
|
||||||
CloseHandle(hWriteIn);
|
|
||||||
CloseHandle(hDupOutFile);
|
|
||||||
}
|
|
||||||
CloseChildHandle(child);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (writing) {
|
|
||||||
*pw = rb_w32_open_osfhandle((long)hDupOutFile,
|
|
||||||
(_O_WRONLY | pipemode));
|
|
||||||
CloseHandle(hWriteIn);
|
|
||||||
if (*pw == -1) {
|
|
||||||
CloseHandle(hDupOutFile);
|
|
||||||
write_open_failed:
|
|
||||||
if (reading) {
|
|
||||||
close(*pr);
|
|
||||||
}
|
|
||||||
CloseChildHandle(child);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = child->pid;
|
ret = child->pid;
|
||||||
} while (0));
|
} while (0));
|
||||||
|
|
||||||
|
@ -2373,6 +2369,108 @@ rb_w32_getservbyport (int port, char *proto)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
socketpair_internal(int af, int type, int protocol, SOCKET *sv)
|
||||||
|
{
|
||||||
|
const char *localhost = NULL;
|
||||||
|
SOCKET svr = INVALID_SOCKET, r = INVALID_SOCKET, w = INVALID_SOCKET;
|
||||||
|
struct sockaddr_in sock_in4;
|
||||||
|
#ifdef INET6
|
||||||
|
struct sockaddr_in6 sock_in6;
|
||||||
|
#endif
|
||||||
|
struct sockaddr *addr;
|
||||||
|
int ret = -1;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (!NtSocketsInitialized) {
|
||||||
|
StartSockets();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (af) {
|
||||||
|
case AF_INET:
|
||||||
|
#if defined PF_INET && PF_INET != AF_INET
|
||||||
|
case PF_INET:
|
||||||
|
#endif
|
||||||
|
sock_in4.sin_family = AF_INET;
|
||||||
|
sock_in4.sin_port = 0;
|
||||||
|
sock_in4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
addr = (struct sockaddr *)&sock_in4;
|
||||||
|
len = sizeof(sock_in4);
|
||||||
|
break;
|
||||||
|
#ifdef INET6
|
||||||
|
case AF_INET6:
|
||||||
|
memset(&sock_in6, 0, sizeof(sock_in6));
|
||||||
|
sock_in6.sin6_family = AF_INET6;
|
||||||
|
sock_in6.sin6_addr = IN6ADDR_LOOPBACK_INIT;
|
||||||
|
addr = (struct sockaddr *)&sock_in6;
|
||||||
|
len = sizeof(sock_in6);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (type != SOCK_STREAM) {
|
||||||
|
errno = EPROTOTYPE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
RUBY_CRITICAL({
|
||||||
|
do {
|
||||||
|
svr = socket(af, type, protocol);
|
||||||
|
if (svr == INVALID_SOCKET)
|
||||||
|
break;
|
||||||
|
if (bind(svr, addr, len) < 0)
|
||||||
|
break;
|
||||||
|
if (getsockname(svr, addr, &len) < 0)
|
||||||
|
break;
|
||||||
|
if (type == SOCK_STREAM)
|
||||||
|
listen(svr, 5);
|
||||||
|
|
||||||
|
w = socket(af, type, protocol);
|
||||||
|
if (w == INVALID_SOCKET)
|
||||||
|
break;
|
||||||
|
if (connect(w, addr, len) < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
r = accept(svr, addr, &len);
|
||||||
|
if (r == INVALID_SOCKET)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
errno = map_errno(WSAGetLastError());
|
||||||
|
if (r != INVALID_SOCKET)
|
||||||
|
closesocket(r);
|
||||||
|
if (w != INVALID_SOCKET)
|
||||||
|
closesocket(w);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sv[0] = r;
|
||||||
|
sv[1] = w;
|
||||||
|
}
|
||||||
|
if (svr != INVALID_SOCKET)
|
||||||
|
closesocket(svr);
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_w32_socketpair(int af, int type, int protocol, int *sv)
|
||||||
|
{
|
||||||
|
SOCKET pair[2];
|
||||||
|
|
||||||
|
if (socketpair_internal(af, type, protocol, pair) < 0)
|
||||||
|
return -1;
|
||||||
|
sv[0] = rb_w32_open_osfhandle(pair[0], O_RDWR|O_BINARY);
|
||||||
|
sv[1] = rb_w32_open_osfhandle(pair[1], O_RDWR|O_BINARY);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Networking stubs
|
// Networking stubs
|
||||||
//
|
//
|
||||||
|
|
|
@ -143,7 +143,7 @@ struct timezone {
|
||||||
#endif
|
#endif
|
||||||
extern void NtInitialize(int *, char ***);
|
extern void NtInitialize(int *, char ***);
|
||||||
extern int rb_w32_cmdvector(const char *, char ***);
|
extern int rb_w32_cmdvector(const char *, char ***);
|
||||||
extern pid_t rb_w32_pipe_exec(const char *, const char *, int, int *, int *);
|
extern pid_t rb_w32_pipe_exec(const char *, const char *, int, int *);
|
||||||
extern int flock(int fd, int oper);
|
extern int flock(int fd, int oper);
|
||||||
extern int rb_w32_is_socket(int);
|
extern int rb_w32_is_socket(int);
|
||||||
extern int rb_w32_accept(int, struct sockaddr *, int *);
|
extern int rb_w32_accept(int, struct sockaddr *, int *);
|
||||||
|
@ -173,6 +173,7 @@ extern struct protoent * rb_w32_getprotobyname(char *);
|
||||||
extern struct protoent * rb_w32_getprotobynumber(int);
|
extern struct protoent * rb_w32_getprotobynumber(int);
|
||||||
extern struct servent * rb_w32_getservbyname(char *, char *);
|
extern struct servent * rb_w32_getservbyname(char *, char *);
|
||||||
extern struct servent * rb_w32_getservbyport(int, char *);
|
extern struct servent * rb_w32_getservbyport(int, char *);
|
||||||
|
extern int rb_w32_socketpair(int, int, int, int *);
|
||||||
extern char * rb_w32_getenv(const char *);
|
extern char * rb_w32_getenv(const char *);
|
||||||
extern int rb_w32_rename(const char *, const char *);
|
extern int rb_w32_rename(const char *, const char *);
|
||||||
extern char **rb_w32_get_environ(void);
|
extern char **rb_w32_get_environ(void);
|
||||||
|
@ -462,6 +463,11 @@ extern char *rb_w32_strerror(int);
|
||||||
#endif
|
#endif
|
||||||
#define getservbyport(p, pr) rb_w32_getservbyport(p, pr)
|
#define getservbyport(p, pr) rb_w32_getservbyport(p, pr)
|
||||||
|
|
||||||
|
#ifdef socketpair
|
||||||
|
#undef socketpair
|
||||||
|
#endif
|
||||||
|
#define socketpair(a, t, p, s) rb_w32_socketpair(a, t, p, s)
|
||||||
|
|
||||||
#ifdef get_osfhandle
|
#ifdef get_osfhandle
|
||||||
#undef get_osfhandle
|
#undef get_osfhandle
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue