From 2f2143a2bef3d2e3d93fbb044c5f066b57cefc2b Mon Sep 17 00:00:00 2001 From: usa Date: Fri, 28 Jun 2002 18:26:01 +0000 Subject: * 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 --- ChangeLog | 12 +++ io.c | 40 ++++++++- version.h | 4 +- win32/win32.c | 283 +++++++++++++++++++++++++++++++++------------------------- win32/win32.h | 14 +-- 5 files changed, 214 insertions(+), 139 deletions(-) diff --git a/ChangeLog b/ChangeLog index f746572d58..3fd1b17aa5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Sat Jun 29 01:43:32 2002 NAKAMURA Usaku + + * 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 * pack.c (pack_unpack): change names of local variables because their diff --git a/io.c b/io.c index 41a5ac91da..591ac8d105 100644 --- a/io.c +++ b/io.c @@ -1761,7 +1761,7 @@ static void pipe_finalize(fptr) OpenFile *fptr; { -#if !defined (__CYGWIN__) +#if !defined (__CYGWIN__) && !defined(NT) extern VALUE rb_last_status; int status; if (fptr->f) { @@ -1803,7 +1803,7 @@ pipe_open(pname, mode) int modef = rb_io_mode_flags(mode); OpenFile *fptr; -#if defined(NT) || defined(DJGPP) || defined(__human68k__) || defined(__VMS) +#if defined(DJGPP) || defined(__human68k__) || defined(__VMS) FILE *f = popen(pname, mode); if (!f) rb_sys_fail(pname); @@ -1821,7 +1821,40 @@ pipe_open(pname, mode) else fptr->f = f; 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 int pid, pr[2], pw[2]; @@ -1908,6 +1941,7 @@ pipe_open(pname, mode) } } #endif +#endif } static VALUE diff --git a/version.h b/version.h index 625bc3eaad..deb44eaa3d 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,4 @@ #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_RELEASE_CODE 20020628 +#define RUBY_RELEASE_CODE 20020629 diff --git a/win32/win32.c b/win32/win32.c index 6f0133b3dc..097aef0ce7 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -299,7 +299,6 @@ char *getlogin() struct ChildRecord { HANDLE hProcess; /* process handle */ pid_t pid; /* process id */ - FILE* pipe; /* pipe */ } ChildRecord[MAXCHILDNUM]; #define FOREACH_CHILD(v) do { \ @@ -328,17 +327,6 @@ FindChildSlot(pid_t pid) 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 CloseChildHandle(struct ChildRecord *child) { @@ -355,7 +343,6 @@ FindFreeChildSlot(void) if (!child->pid) { child->pid = -1; /* lock the slot */ child->hProcess = NULL; - child->pipe = NULL; return child; } } END_FOREACH_CHILD; @@ -443,149 +430,203 @@ rb_w32_get_osfhandle(int fh) } - -FILE * -rb_w32_popen (char *cmd, char *mode) +pid_t +pipe_exec(char *cmd, int mode, FILE **fpr, FILE **fpw) { - FILE *fp; - int reading; - int pipemode; struct ChildRecord* child; - BOOL fRet; - HANDLE hInFile, hOutFile, hSavedStdIo, hDupFile; + HANDLE hReadIn, hReadOut; + HANDLE hWriteIn, hWriteOut; + HANDLE hSavedStdIn, hSavedStdOut; + HANDLE hDupInFile, hDupOutFile; HANDLE hCurProc; SECURITY_ATTRIBUTES sa; - int fd; - - // - // Figure out what we're doing... - // + BOOL fRet; + BOOL reading, writing; + int fdin, fdout; + int pipemode; + char modes[3]; + int ret; - reading = (*mode == 'r') ? TRUE : FALSE; - pipemode = (*(mode+1) == 'b') ? O_BINARY : O_TEXT; + /* 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; - // - // Now get a pipe - // sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; - fRet = CreatePipe(&hInFile, &hOutFile, &sa, 2048L); - if (!fRet) { - errno = GetLastError(); - return NULL; - } - - /* save parent's STDIO and redirect for child */ - hCurProc = GetCurrentProcess(); - if (reading) { - hSavedStdIo = GetStdHandle(STD_OUTPUT_HANDLE); - if (!SetStdHandle(STD_OUTPUT_HANDLE, hOutFile) || - !DuplicateHandle(hCurProc, hInFile, hCurProc, &hDupFile, 0, FALSE, - DUPLICATE_SAME_ACCESS)) { - errno = GetLastError(); - CloseHandle(hInFile); - CloseHandle(hOutFile); - CloseHandle(hCurProc); - return NULL; + /* create pipe, save parent's STDIN/STDOUT and redirect them for child */ + RUBY_CRITICAL(do { + ret = -1; + hCurProc = GetCurrentProcess(); + if (reading) { + fRet = CreatePipe(&hReadIn, &hReadOut, &sa, 2048L); + if (!fRet) { + errno = GetLastError(); + break; + } + hSavedStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + if (!SetStdHandle(STD_OUTPUT_HANDLE, hReadOut) || + !DuplicateHandle(hCurProc, hReadIn, hCurProc, &hDupInFile, 0, + FALSE, DUPLICATE_SAME_ACCESS)) { + errno = GetLastError(); + CloseHandle(hReadIn); + CloseHandle(hReadOut); + CloseHandle(hCurProc); + break; + } + CloseHandle(hReadIn); } - CloseHandle(hInFile); - } - else { - hSavedStdIo = GetStdHandle(STD_INPUT_HANDLE); - if (!SetStdHandle(STD_INPUT_HANDLE, hInFile) || - !DuplicateHandle(hCurProc, hOutFile, hCurProc, &hDupFile, 0, FALSE, - DUPLICATE_SAME_ACCESS)) { - errno = GetLastError(); - CloseHandle(hInFile); - CloseHandle(hOutFile); - CloseHandle(hCurProc); - return NULL; + 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(hOutFile); + CloseHandle(hCurProc); + ret = 0; + } while (0)); + if (ret != 0) { + return ret; } - CloseHandle(hCurProc); /* create child process */ child = CreateChild(cmd, &sa, NULL, NULL, NULL); if (!child) { - CloseHandle(reading ? hOutFile : hInFile); - CloseHandle(hDupFile); - return NULL; + RUBY_CRITICAL({ + if (reading) { + SetStdHandle(STD_OUTPUT_HANDLE, hSavedStdOut); + CloseHandle(hReadOut); + CloseHandle(hDupInFile); + } + if (writing) { + SetStdHandle(STD_INPUT_HANDLE, hSavedStdIn); + CloseHandle(hWriteIn); + CloseHandle(hDupOutFile); + } + }); + return -1; + } + + /* restore STDIN/STDOUT */ + RUBY_CRITICAL(do { + ret = -1; + if (reading) { + if (!SetStdHandle(STD_OUTPUT_HANDLE, hSavedStdOut)) { + errno = GetLastError(); + CloseChildHandle(child); + CloseHandle(hReadOut); + CloseHandle(hDupInFile); + if (writing) { + CloseHandle(hWriteIn); + CloseHandle(hDupOutFile); + } + break; + } + } + if (writing) { + if (!SetStdHandle(STD_INPUT_HANDLE, hSavedStdIn)) { + errno = GetLastError(); + CloseChildHandle(child); + CloseHandle(hWriteIn); + CloseHandle(hDupOutFile); + if (reading) { + CloseHandle(hReadOut); + CloseHandle(hDupInFile); + } + break; + } + } + ret = 0; + } while (0)); + if (ret != 0) { + return ret; } - /* restore STDIO */ if (reading) { - if (!SetStdHandle(STD_OUTPUT_HANDLE, hSavedStdIo)) { - errno = GetLastError(); +#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); - CloseHandle(hDupFile); - CloseHandle(hOutFile); - return NULL; + return -1; } } - else { - if (!SetStdHandle(STD_INPUT_HANDLE, hSavedStdIo)) { - errno = GetLastError(); + 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); - CloseHandle(hInFile); - CloseHandle(hDupFile); - return NULL; + return -1; } } if (reading) { - fd = _open_osfhandle((long)hDupFile, (_O_RDONLY | pipemode)); - CloseHandle(hOutFile); - } - else { - fd = _open_osfhandle((long)hDupFile, (_O_WRONLY | pipemode)); - CloseHandle(hInFile); - } - - if (fd == -1) { - CloseHandle(hDupFile); - CloseChildHandle(child); - return NULL; + sprintf(modes, "r%s", pipemode == O_BINARY ? "b" : ""); + if ((*fpr = (FILE *)fdopen(fdin, modes)) == NULL) { + _close(fdin); + if (writing) { + _close(fdout); + } + CloseChildHandle(child); + return -1; + } } - - if ((fp = (FILE *) fdopen(fd, mode)) == NULL) { - _close(fd); - CloseChildHandle(child); - return NULL; + if (writing) { + sprintf(modes, "w%s", pipemode == O_BINARY ? "b" : ""); + if ((*fpw = (FILE *)fdopen(fdout, modes)) == NULL) { + _close(fdout); + if (reading) { + fclose(*fpr); + } + CloseChildHandle(child); + return -1; + } } - child->pipe = fp; - - return fp; + return child->pid; } 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 do_spawn(cmd) char *cmd; diff --git a/win32/win32.h b/win32/win32.h index c33405110d..c5873c62b7 100644 --- a/win32/win32.h +++ b/win32/win32.h @@ -145,11 +145,8 @@ extern "C++" { #define utime _utime #define vsnprintf _vsnprintf #define snprintf _snprintf -#define popen _popen -#define pclose _pclose #undef stat #define stat(path,st) rb_w32_stat(path,st) -/* these are defined in nt.c */ #ifdef __MINGW32__ struct timezone { @@ -161,8 +158,7 @@ extern int NtMakeCmdVector(char *, char ***, int); extern void NtInitialize(int *, char ***); extern char * NtGetLib(void); extern char * NtGetBin(void); -extern FILE * rb_w32_popen(char *, char *); -extern int rb_w32_pclose(FILE *); +extern pid_t pipe_exec(char *, int, FILE **, FILE **); extern int flock(int fd, int oper); extern int rb_w32_fddup(int); extern void rb_w32_fdclose(FILE *); @@ -276,14 +272,6 @@ extern char *rb_w32_strerror(int); #define EWOULDBLOCK 10035 /* EBASEERR + 35 (winsock.h) */ #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_end */ -- cgit v1.2.3