* io.c (pipe_finalize, pipe_popen): two-way pipe support for win32.

* win32/win32.c (ChildRecord, FindFreeChildSlot): ditto.

* win32/win32.c, win32/win32.h (pipe_exec): new function for two-way
  pipe support for win32.

* win32/win32.c, win32/win32.h (FindPipedChildSlot, rb_w32_popen,
  rb_w32_pclose): removed functions for two-way pipe support for win32.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2610 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
usa 2002-06-28 18:26:01 +00:00
parent cd6cffa7b6
commit 2f2143a2be
5 changed files with 214 additions and 139 deletions

View File

@ -1,3 +1,15 @@
Sat Jun 29 01:43:32 2002 NAKAMURA Usaku <usa@ruby-lang.org>
* io.c (pipe_finalize, pipe_popen): two-way pipe support for win32.
* win32/win32.c (ChildRecord, FindFreeChildSlot): ditto.
* win32/win32.c, win32/win32.h (pipe_exec): new function for two-way
pipe support for win32.
* win32/win32.c, win32/win32.h (FindPipedChildSlot, rb_w32_popen,
rb_w32_pclose): removed functions for two-way pipe support for win32.
Fri Jun 28 23:49:34 2002 NAKAMURA Usaku <usa@ruby-lang.org> Fri Jun 28 23:49:34 2002 NAKAMURA Usaku <usa@ruby-lang.org>
* pack.c (pack_unpack): change names of local variables because their * pack.c (pack_unpack): change names of local variables because their

40
io.c
View File

@ -1761,7 +1761,7 @@ static void
pipe_finalize(fptr) pipe_finalize(fptr)
OpenFile *fptr; OpenFile *fptr;
{ {
#if !defined (__CYGWIN__) #if !defined (__CYGWIN__) && !defined(NT)
extern VALUE rb_last_status; extern VALUE rb_last_status;
int status; int status;
if (fptr->f) { if (fptr->f) {
@ -1803,7 +1803,7 @@ pipe_open(pname, mode)
int modef = rb_io_mode_flags(mode); int modef = rb_io_mode_flags(mode);
OpenFile *fptr; OpenFile *fptr;
#if defined(NT) || defined(DJGPP) || defined(__human68k__) || defined(__VMS) #if defined(DJGPP) || defined(__human68k__) || defined(__VMS)
FILE *f = popen(pname, mode); FILE *f = popen(pname, mode);
if (!f) rb_sys_fail(pname); if (!f) rb_sys_fail(pname);
@ -1821,7 +1821,40 @@ pipe_open(pname, mode)
else fptr->f = f; else fptr->f = f;
rb_io_synchronized(fptr); rb_io_synchronized(fptr);
} }
return port; return (VALUE)port;
}
#else
#if defined(NT)
int pid;
FILE *fpr, *fpw;
retry:
pid = pipe_exec(pname, rb_io_mode_modenum(mode), &fpr, &fpw);
if (pid == -1) { /* exec failed */
if (errno == EAGAIN) {
rb_thread_sleep(1);
goto retry;
}
rb_sys_fail(pname);
}
else {
VALUE port = rb_obj_alloc(rb_cIO);
MakeOpenFile(port, fptr);
fptr->mode = modef;
fptr->mode |= FMODE_SYNC;
fptr->pid = pid;
if (modef & FMODE_READABLE) {
fptr->f = fpr;
}
if (modef & FMODE_WRITABLE) {
if (fptr->f) fptr->f2 = fpw;
else fptr->f = fpw;
}
fptr->finalize = pipe_finalize;
pipe_add_fptr(fptr);
return (VALUE)port;
} }
#else #else
int pid, pr[2], pw[2]; int pid, pr[2], pw[2];
@ -1908,6 +1941,7 @@ pipe_open(pname, mode)
} }
} }
#endif #endif
#endif
} }
static VALUE static VALUE

View File

@ -1,4 +1,4 @@
#define RUBY_VERSION "1.7.2" #define RUBY_VERSION "1.7.2"
#define RUBY_RELEASE_DATE "2002-06-28" #define RUBY_RELEASE_DATE "2002-06-29"
#define RUBY_VERSION_CODE 172 #define RUBY_VERSION_CODE 172
#define RUBY_RELEASE_CODE 20020628 #define RUBY_RELEASE_CODE 20020629

View File

@ -299,7 +299,6 @@ char *getlogin()
struct ChildRecord { struct ChildRecord {
HANDLE hProcess; /* process handle */ HANDLE hProcess; /* process handle */
pid_t pid; /* process id */ pid_t pid; /* process id */
FILE* pipe; /* pipe */
} ChildRecord[MAXCHILDNUM]; } ChildRecord[MAXCHILDNUM];
#define FOREACH_CHILD(v) do { \ #define FOREACH_CHILD(v) do { \
@ -328,17 +327,6 @@ FindChildSlot(pid_t pid)
return NULL; return NULL;
} }
static struct ChildRecord *
FindPipedChildSlot(FILE *fp)
{
FOREACH_CHILD(child) {
if (child->pid && child->pipe == fp) {
return child;
}
} END_FOREACH_CHILD;
return NULL;
}
static void static void
CloseChildHandle(struct ChildRecord *child) CloseChildHandle(struct ChildRecord *child)
{ {
@ -355,7 +343,6 @@ FindFreeChildSlot(void)
if (!child->pid) { if (!child->pid) {
child->pid = -1; /* lock the slot */ child->pid = -1; /* lock the slot */
child->hProcess = NULL; child->hProcess = NULL;
child->pipe = NULL;
return child; return child;
} }
} END_FOREACH_CHILD; } END_FOREACH_CHILD;
@ -443,149 +430,203 @@ rb_w32_get_osfhandle(int fh)
} }
pid_t
FILE * pipe_exec(char *cmd, int mode, FILE **fpr, FILE **fpw)
rb_w32_popen (char *cmd, char *mode)
{ {
FILE *fp;
int reading;
int pipemode;
struct ChildRecord* child; struct ChildRecord* child;
BOOL fRet; HANDLE hReadIn, hReadOut;
HANDLE hInFile, hOutFile, hSavedStdIo, hDupFile; HANDLE hWriteIn, hWriteOut;
HANDLE hSavedStdIn, hSavedStdOut;
HANDLE hDupInFile, hDupOutFile;
HANDLE hCurProc; HANDLE hCurProc;
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
int fd; BOOL fRet;
BOOL reading, writing;
int fdin, fdout;
int pipemode;
char modes[3];
int ret;
// /* Figure out what we're doing... */
// Figure out what we're doing... writing = (mode & (O_WRONLY | O_RDWR)) ? TRUE : FALSE;
// reading = ((mode & O_RDWR) || !writing) ? TRUE : FALSE;
pipemode = (mode & O_BINARY) ? O_BINARY : O_TEXT;
reading = (*mode == 'r') ? TRUE : FALSE;
pipemode = (*(mode+1) == 'b') ? O_BINARY : O_TEXT;
//
// Now get a pipe
//
sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.nLength = sizeof (SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE; sa.bInheritHandle = TRUE;
fRet = CreatePipe(&hInFile, &hOutFile, &sa, 2048L); /* create pipe, save parent's STDIN/STDOUT and redirect them for child */
if (!fRet) { RUBY_CRITICAL(do {
errno = GetLastError(); ret = -1;
return NULL;
}
/* save parent's STDIO and redirect for child */
hCurProc = GetCurrentProcess(); hCurProc = GetCurrentProcess();
if (reading) { if (reading) {
hSavedStdIo = GetStdHandle(STD_OUTPUT_HANDLE); fRet = CreatePipe(&hReadIn, &hReadOut, &sa, 2048L);
if (!SetStdHandle(STD_OUTPUT_HANDLE, hOutFile) || if (!fRet) {
!DuplicateHandle(hCurProc, hInFile, hCurProc, &hDupFile, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
errno = GetLastError(); errno = GetLastError();
CloseHandle(hInFile); break;
CloseHandle(hOutFile);
CloseHandle(hCurProc);
return NULL;
} }
CloseHandle(hInFile); hSavedStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
} if (!SetStdHandle(STD_OUTPUT_HANDLE, hReadOut) ||
else { !DuplicateHandle(hCurProc, hReadIn, hCurProc, &hDupInFile, 0,
hSavedStdIo = GetStdHandle(STD_INPUT_HANDLE); FALSE, DUPLICATE_SAME_ACCESS)) {
if (!SetStdHandle(STD_INPUT_HANDLE, hInFile) ||
!DuplicateHandle(hCurProc, hOutFile, hCurProc, &hDupFile, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
errno = GetLastError(); errno = GetLastError();
CloseHandle(hInFile); CloseHandle(hReadIn);
CloseHandle(hOutFile); CloseHandle(hReadOut);
CloseHandle(hCurProc); CloseHandle(hCurProc);
return NULL; break;
} }
CloseHandle(hOutFile); CloseHandle(hReadIn);
}
if (writing) {
fRet = CreatePipe(&hWriteIn, &hWriteOut, &sa, 2048L);
if (!fRet) {
errno = GetLastError();
if (reading) {
CloseHandle(hDupInFile);
CloseHandle(hReadOut);
}
break;
}
hSavedStdIn = GetStdHandle(STD_INPUT_HANDLE);
if (!SetStdHandle(STD_INPUT_HANDLE, hWriteIn) ||
!DuplicateHandle(hCurProc, hWriteOut, hCurProc, &hDupOutFile, 0,
FALSE, DUPLICATE_SAME_ACCESS)) {
errno = GetLastError();
CloseHandle(hWriteIn);
CloseHandle(hWriteOut);
CloseHandle(hCurProc);
if (reading) {
CloseHandle(hDupInFile);
CloseHandle(hReadOut);
}
break;
}
CloseHandle(hWriteOut);
} }
CloseHandle(hCurProc); CloseHandle(hCurProc);
ret = 0;
} while (0));
if (ret != 0) {
return ret;
}
/* create child process */ /* create child process */
child = CreateChild(cmd, &sa, NULL, NULL, NULL); child = CreateChild(cmd, &sa, NULL, NULL, NULL);
if (!child) { if (!child) {
CloseHandle(reading ? hOutFile : hInFile); RUBY_CRITICAL({
CloseHandle(hDupFile); if (reading) {
return NULL; SetStdHandle(STD_OUTPUT_HANDLE, hSavedStdOut);
CloseHandle(hReadOut);
CloseHandle(hDupInFile);
}
if (writing) {
SetStdHandle(STD_INPUT_HANDLE, hSavedStdIn);
CloseHandle(hWriteIn);
CloseHandle(hDupOutFile);
}
});
return -1;
} }
/* restore STDIO */ /* restore STDIN/STDOUT */
RUBY_CRITICAL(do {
ret = -1;
if (reading) { if (reading) {
if (!SetStdHandle(STD_OUTPUT_HANDLE, hSavedStdIo)) { if (!SetStdHandle(STD_OUTPUT_HANDLE, hSavedStdOut)) {
errno = GetLastError(); errno = GetLastError();
CloseChildHandle(child); CloseChildHandle(child);
CloseHandle(hDupFile); CloseHandle(hReadOut);
CloseHandle(hOutFile); CloseHandle(hDupInFile);
return NULL; if (writing) {
CloseHandle(hWriteIn);
CloseHandle(hDupOutFile);
}
break;
} }
} }
else { if (writing) {
if (!SetStdHandle(STD_INPUT_HANDLE, hSavedStdIo)) { if (!SetStdHandle(STD_INPUT_HANDLE, hSavedStdIn)) {
errno = GetLastError(); errno = GetLastError();
CloseChildHandle(child); CloseChildHandle(child);
CloseHandle(hInFile); CloseHandle(hWriteIn);
CloseHandle(hDupFile); CloseHandle(hDupOutFile);
return NULL; if (reading) {
CloseHandle(hReadOut);
CloseHandle(hDupInFile);
}
break;
}
}
ret = 0;
} while (0));
if (ret != 0) {
return ret;
}
if (reading) {
#ifdef __BORLANDC__
fdin = _open_osfhandle((long)hDupInFile, (_O_RDONLY | pipemode));
#else
fdin = rb_w32_open_osfhandle((long)hDupInFile, (_O_RDONLY | pipemode));
#endif
CloseHandle(hReadOut);
if (fdin == -1) {
CloseHandle(hDupInFile);
if (writing) {
CloseHandle(hWriteIn);
CloseHandle(hDupOutFile);
}
CloseChildHandle(child);
return -1;
}
}
if (writing) {
#ifdef __BORLANDC__
fdout = _open_osfhandle((long)hDupOutFile, (_O_WRONLY | pipemode));
#else
fdout = rb_w32_open_osfhandle((long)hDupOutFile,
(_O_WRONLY | pipemode));
#endif
CloseHandle(hWriteIn);
if (fdout == -1) {
CloseHandle(hDupOutFile);
if (reading) {
_close(fdin);
}
CloseChildHandle(child);
return -1;
} }
} }
if (reading) { if (reading) {
fd = _open_osfhandle((long)hDupFile, (_O_RDONLY | pipemode)); sprintf(modes, "r%s", pipemode == O_BINARY ? "b" : "");
CloseHandle(hOutFile); if ((*fpr = (FILE *)fdopen(fdin, modes)) == NULL) {
_close(fdin);
if (writing) {
_close(fdout);
} }
else {
fd = _open_osfhandle((long)hDupFile, (_O_WRONLY | pipemode));
CloseHandle(hInFile);
}
if (fd == -1) {
CloseHandle(hDupFile);
CloseChildHandle(child); CloseChildHandle(child);
return NULL; return -1;
}
}
if (writing) {
sprintf(modes, "w%s", pipemode == O_BINARY ? "b" : "");
if ((*fpw = (FILE *)fdopen(fdout, modes)) == NULL) {
_close(fdout);
if (reading) {
fclose(*fpr);
} }
if ((fp = (FILE *) fdopen(fd, mode)) == NULL) {
_close(fd);
CloseChildHandle(child); CloseChildHandle(child);
return NULL; return -1;
}
} }
child->pipe = fp; return child->pid;
return fp;
} }
extern VALUE rb_last_status; extern VALUE rb_last_status;
int
rb_w32_pclose(FILE *fp)
{
struct ChildRecord *child = FindPipedChildSlot(fp);
if (!child) {
return -1; /* may closed in waitpid() */
}
//
// close the pipe
//
child->pipe = NULL;
fflush(fp);
fclose(fp);
//
// get the return status of the process
//
rb_syswait(child->pid);
return NUM2INT(rb_last_status);
}
int int
do_spawn(cmd) do_spawn(cmd)
char *cmd; char *cmd;

View File

@ -145,11 +145,8 @@ extern "C++" {
#define utime _utime #define utime _utime
#define vsnprintf _vsnprintf #define vsnprintf _vsnprintf
#define snprintf _snprintf #define snprintf _snprintf
#define popen _popen
#define pclose _pclose
#undef stat #undef stat
#define stat(path,st) rb_w32_stat(path,st) #define stat(path,st) rb_w32_stat(path,st)
/* these are defined in nt.c */
#ifdef __MINGW32__ #ifdef __MINGW32__
struct timezone { struct timezone {
@ -161,8 +158,7 @@ extern int NtMakeCmdVector(char *, char ***, int);
extern void NtInitialize(int *, char ***); extern void NtInitialize(int *, char ***);
extern char * NtGetLib(void); extern char * NtGetLib(void);
extern char * NtGetBin(void); extern char * NtGetBin(void);
extern FILE * rb_w32_popen(char *, char *); extern pid_t pipe_exec(char *, int, FILE **, FILE **);
extern int rb_w32_pclose(FILE *);
extern int flock(int fd, int oper); extern int flock(int fd, int oper);
extern int rb_w32_fddup(int); extern int rb_w32_fddup(int);
extern void rb_w32_fdclose(FILE *); extern void rb_w32_fdclose(FILE *);
@ -276,14 +272,6 @@ extern char *rb_w32_strerror(int);
#define EWOULDBLOCK 10035 /* EBASEERR + 35 (winsock.h) */ #define EWOULDBLOCK 10035 /* EBASEERR + 35 (winsock.h) */
#endif #endif
#ifdef popen
#undef popen
#define popen rb_w32_popen
#endif
#ifdef pclose
#undef pclose
#define pclose rb_w32_pclose
#endif
/* #undef va_start */ /* #undef va_start */
/* #undef va_end */ /* #undef va_end */