зеркало из https://github.com/github/ruby.git
* 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:
Родитель
6100eced2e
Коммит
c3ce319d7d
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>
|
||||
|
||||
* 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;
|
||||
volatile int doexec;
|
||||
#elif defined(_WIN32)
|
||||
int r, w;
|
||||
int fd;
|
||||
int openmode = rb_io_mode_modenum(mode);
|
||||
char *exename = NULL;
|
||||
#endif
|
||||
|
@ -2895,7 +2895,7 @@ pipe_open(argc, argv, mode)
|
|||
else {
|
||||
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 */
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
|
@ -2910,14 +2910,13 @@ pipe_open(argc, argv, mode)
|
|||
}
|
||||
}
|
||||
if ((modef & FMODE_READABLE) && (modef & FMODE_WRITABLE)) {
|
||||
close(w);
|
||||
fp = rb_fdopen(r, "r+");
|
||||
fp = rb_fdopen(fd, "r+");
|
||||
}
|
||||
else if (modef & FMODE_READABLE) {
|
||||
fp = rb_fdopen(r, "r");
|
||||
fp = rb_fdopen(fd, "r");
|
||||
}
|
||||
else {
|
||||
fp = rb_fdopen(w, "w");
|
||||
fp = rb_fdopen(fd, "w");
|
||||
}
|
||||
#else
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static int socketpair_internal(int af, int type, int protocol, SOCKET *sv);
|
||||
|
||||
pid_t
|
||||
rb_w32_pipe_exec(const char *cmd, const char *prog, int mode,
|
||||
int *pr, int *pw)
|
||||
rb_w32_pipe_exec(const char *cmd, const char *prog, int mode, int *pipe)
|
||||
{
|
||||
struct ChildRecord* child;
|
||||
HANDLE hReadIn, hReadOut;
|
||||
HANDLE hWriteIn, hWriteOut;
|
||||
HANDLE hDupInFile, hDupOutFile;
|
||||
HANDLE hOrg, hIn, hOut;
|
||||
HANDLE hDupFile;
|
||||
HANDLE hCurProc;
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
BOOL fRet;
|
||||
BOOL reading, writing;
|
||||
SOCKET pair[2];
|
||||
int fd;
|
||||
int pipemode;
|
||||
int ret;
|
||||
|
||||
/* Figure out what we're doing... */
|
||||
writing = (mode & (O_WRONLY | O_RDWR)) ? TRUE : FALSE;
|
||||
reading = ((mode & O_RDWR) || !writing) ? TRUE : FALSE;
|
||||
if (mode & O_BINARY) {
|
||||
pipemode = O_BINARY;
|
||||
if (mode & O_RDWR) {
|
||||
reading = writing = TRUE;
|
||||
pipemode = _O_RDWR;
|
||||
}
|
||||
else if (mode & O_WRONLY) {
|
||||
reading = FALSE;
|
||||
writing = TRUE;
|
||||
pipemode = _O_WRONLY;
|
||||
}
|
||||
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.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = TRUE;
|
||||
ret = -1;
|
||||
hWriteIn = hReadOut = NULL;
|
||||
|
||||
RUBY_CRITICAL(do {
|
||||
/* create pipe */
|
||||
hCurProc = GetCurrentProcess();
|
||||
if (reading) {
|
||||
fRet = CreatePipe(&hReadIn, &hReadOut, &sa, 2048L);
|
||||
if (!fRet) {
|
||||
errno = map_errno(GetLastError());
|
||||
if (reading && writing) {
|
||||
if (socketpair_internal(AF_INET, SOCK_STREAM, 0, pair) < 0) {
|
||||
break;
|
||||
}
|
||||
if (!DuplicateHandle(hCurProc, hReadIn, hCurProc, &hDupInFile, 0,
|
||||
FALSE, DUPLICATE_SAME_ACCESS)) {
|
||||
if (!DuplicateHandle(hCurProc, (HANDLE)pair[1], hCurProc,
|
||||
&hDupFile, 0, FALSE,
|
||||
DUPLICATE_SAME_ACCESS)) {
|
||||
errno = map_errno(GetLastError());
|
||||
CloseHandle(hReadIn);
|
||||
CloseHandle(hReadOut);
|
||||
CloseHandle((HANDLE)pair[0]);
|
||||
CloseHandle((HANDLE)pair[1]);
|
||||
CloseHandle(hCurProc);
|
||||
break;
|
||||
}
|
||||
CloseHandle(hReadIn);
|
||||
hOrg = hIn = hOut = (HANDLE)pair[0];
|
||||
}
|
||||
if (writing) {
|
||||
fRet = CreatePipe(&hWriteIn, &hWriteOut, &sa, 2048L);
|
||||
else if (reading) {
|
||||
fRet = CreatePipe(&hIn, &hOut, &sa, 2048L);
|
||||
if (!fRet) {
|
||||
errno = map_errno(GetLastError());
|
||||
write_pipe_failed:
|
||||
if (reading) {
|
||||
CloseHandle(hDupInFile);
|
||||
CloseHandle(hReadOut);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!DuplicateHandle(hCurProc, hWriteOut, hCurProc, &hDupOutFile, 0,
|
||||
if (!DuplicateHandle(hCurProc, hIn, hCurProc, &hDupFile, 0,
|
||||
FALSE, DUPLICATE_SAME_ACCESS)) {
|
||||
errno = map_errno(GetLastError());
|
||||
CloseHandle(hWriteIn);
|
||||
CloseHandle(hWriteOut);
|
||||
CloseHandle(hIn);
|
||||
CloseHandle(hOut);
|
||||
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);
|
||||
|
||||
/* create child process */
|
||||
child = CreateChild(cmd, prog, &sa, hWriteIn, hReadOut, NULL);
|
||||
child = CreateChild(cmd, prog, &sa, hIn, hOut, NULL);
|
||||
if (!child) {
|
||||
if (reading) {
|
||||
CloseHandle(hReadOut);
|
||||
CloseHandle(hDupInFile);
|
||||
}
|
||||
if (writing) {
|
||||
CloseHandle(hWriteIn);
|
||||
CloseHandle(hDupOutFile);
|
||||
}
|
||||
CloseHandle(hOrg);
|
||||
CloseHandle(hDupFile);
|
||||
break;
|
||||
}
|
||||
|
||||
/* associate handle to fp */
|
||||
if (reading) {
|
||||
*pr = rb_w32_open_osfhandle((long)hDupInFile,
|
||||
(_O_RDONLY | pipemode));
|
||||
CloseHandle(hReadOut);
|
||||
if (*pr == -1) {
|
||||
CloseHandle(hDupInFile);
|
||||
read_open_failed:
|
||||
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;
|
||||
}
|
||||
/* associate handle to file descritor */
|
||||
*pipe = rb_w32_open_osfhandle((long)hDupFile, pipemode);
|
||||
if (!(reading && writing))
|
||||
CloseHandle(hOrg);
|
||||
if (*pipe == -1) {
|
||||
CloseHandle(hDupFile);
|
||||
CloseChildHandle(child);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = child->pid;
|
||||
} while (0));
|
||||
|
||||
|
@ -2373,6 +2369,108 @@ rb_w32_getservbyport (int port, char *proto)
|
|||
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
|
||||
//
|
||||
|
|
|
@ -143,7 +143,7 @@ struct timezone {
|
|||
#endif
|
||||
extern void NtInitialize(int *, 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 rb_w32_is_socket(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 servent * rb_w32_getservbyname(char *, 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 int rb_w32_rename(const char *, const char *);
|
||||
extern char **rb_w32_get_environ(void);
|
||||
|
@ -462,6 +463,11 @@ extern char *rb_w32_strerror(int);
|
|||
#endif
|
||||
#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
|
||||
#undef get_osfhandle
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче