From 8a61b67d502ed4fbd5f480ca9458884b55ce7a95 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 27 May 2015 15:14:20 +0100 Subject: mingw: add routine to pipe a file descriptor to/from a command --- include/mingw.h | 1 + win32/popen.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 129 insertions(+), 18 deletions(-) diff --git a/include/mingw.h b/include/mingw.h index d6ed909b5..bf8cd0c4c 100644 --- a/include/mingw.h +++ b/include/mingw.h @@ -142,6 +142,7 @@ int mingw_rename(const char*, const char*); #define rename mingw_rename FILE *mingw_popen(const char *cmd, const char *mode); +int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid); int mingw_pclose(FILE *fd); #undef popen #undef pclose diff --git a/win32/popen.c b/win32/popen.c index a7b2c7ec9..93d51bb55 100644 --- a/win32/popen.c +++ b/win32/popen.c @@ -26,24 +26,10 @@ static int mingw_pipe(HANDLE *readwrite) return 0; } -FILE *mingw_popen(const char *cmd, const char *mode) +static pipe_data *find_pipe(void) { int i; pipe_data *p = NULL; - FILE *fptr = NULL; - STARTUPINFO siStartInfo; - int success; - int fd; - int len, count; - int ip, ic; - char *cmd_buff = NULL; - const char *s; - char *t; - - if ( cmd == NULL || *cmd == '\0' || mode == NULL || - (*mode != 'r' && *mode != 'w') ) { - return NULL; - } /* find an unused pipe structure */ for ( i=0; ipipe[0] = INVALID_HANDLE_VALUE; + p->pipe[1] = INVALID_HANDLE_VALUE; + + return p; +} + +FILE *mingw_popen(const char *cmd, const char *mode) +{ + pipe_data *p; + FILE *fptr = NULL; + STARTUPINFO siStartInfo; + int success; + int fd; + int len, count; + int ip, ic; + char *cmd_buff = NULL; + const char *s; + char *t; + + if ( cmd == NULL || *cmd == '\0' || mode == NULL || + (*mode != 'r' && *mode != 'w') ) { + return NULL; + } + + /* find an unused pipe structure */ + if ( (p=find_pipe()) == NULL ) { + return NULL; + } + /* count double quotes */ count = 0; for ( s=cmd; *s; ++s ) { @@ -91,9 +106,6 @@ FILE *mingw_popen(const char *cmd, const char *mode) *t++ = '"'; *t = '\0'; - p->pipe[0] = INVALID_HANDLE_VALUE; - p->pipe[1] = INVALID_HANDLE_VALUE; - /* Create the pipe */ if ( mingw_pipe(p->pipe) == -1 ) { goto finito; @@ -168,6 +180,104 @@ finito: return fptr; } +/* + * Open a pipe to a command where the file descriptor fd0 is used + * as input to the command (read mode) or as the destination of the + * output from the command (write mode). The pid of the command is + * returned in the variable pid, which can be NULL. + */ +int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid) +{ + pipe_data *p; + STARTUPINFO siStartInfo; + int success; + int fd = -1; + int ip, ic; + + if ( cmd == NULL || *cmd == '\0' || mode == NULL || + (*mode != 'r' && *mode != 'w') ) { + return -1; + } + + /* find an unused pipe structure */ + if ( (p=find_pipe()) == NULL ) { + return -1; + } + + /* Create the pipe */ + if ( mingw_pipe(p->pipe) == -1 ) { + goto finito; + } + + /* index of parent end of pipe */ + ip = !(*mode == 'r'); + /* index of child end of pipe */ + ic = (*mode == 'r'); + + /* Make the parent end of the pipe non-inheritable */ + SetHandleInformation(p->pipe[ip], HANDLE_FLAG_INHERIT, 0); + + /* Now create the child process */ + ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); + siStartInfo.cb = sizeof(STARTUPINFO); + if ( *mode == 'r' ) { + siStartInfo.hStdInput = (HANDLE)_get_osfhandle(fd0); + siStartInfo.hStdOutput = p->pipe[ic]; + } + else { + siStartInfo.hStdInput = p->pipe[ic]; + siStartInfo.hStdOutput = (HANDLE)_get_osfhandle(fd0); + } + siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); + siStartInfo.wShowWindow = SW_HIDE; + siStartInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; + + success = CreateProcess(NULL, + (LPTSTR)cmd, /* command line */ + NULL, /* process security attributes */ + NULL, /* primary thread security attributes */ + TRUE, /* handles are inherited */ + 0, /* creation flags */ + NULL, /* use parent's environment */ + NULL, /* use parent's current directory */ + &siStartInfo, /* STARTUPINFO pointer */ + &p->piProcInfo); /* receives PROCESS_INFORMATION */ + + if ( !success ) { + goto finito; + } + + /* close child end of pipe */ + CloseHandle(p->pipe[ic]); + p->pipe[ic] = INVALID_HANDLE_VALUE; + + if ( *mode == 'r' ) { + fd = _open_osfhandle((long)p->pipe[ip], _O_RDONLY|_O_BINARY); + } + else { + fd = _open_osfhandle((long)p->pipe[ip], _O_WRONLY|_O_BINARY); + } + +finito: + if ( fd == -1 ) { + if ( p->pipe[0] != INVALID_HANDLE_VALUE ) { + CloseHandle(p->pipe[0]); + } + if ( p->pipe[1] != INVALID_HANDLE_VALUE ) { + CloseHandle(p->pipe[1]); + } + } + else { + p->mode = *mode; + p->fd = fd; + if ( pid ) { + *pid = (pid_t)p->piProcInfo.dwProcessId; + } + } + + return fd; +} + int mingw_pclose(FILE *fp) { int i, ip, fd; -- cgit v1.2.3-55-g6feb