#include #include "libbb.h" typedef struct { PROCESS_INFORMATION piProcInfo; HANDLE pipe[2]; char mode; int fd; } pipe_data; static pipe_data *pipes = NULL; static int num_pipes = 0; static int mingw_pipe(HANDLE *readwrite) { SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); /* Length in bytes */ sa.bInheritHandle = 1; /* the child must inherit these handles */ sa.lpSecurityDescriptor = NULL; if ( !CreatePipe (&readwrite[0], &readwrite[1], &sa, 1 << 13) ) { return -1; } return 0; } FILE *mingw_popen(const char *cmd, const char *mode) { 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; /* 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 = GetStdHandle(STD_INPUT_HANDLE); siStartInfo.hStdOutput = p->pipe[ic]; } else { siStartInfo.hStdInput = p->pipe[ic]; siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); } siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); siStartInfo.wShowWindow = SW_HIDE; siStartInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; success = CreateProcess(NULL, (LPTSTR)cmd_buff, /* 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); fptr = _fdopen(fd, "rb"); } else { fd = _open_osfhandle((long)p->pipe[ip], _O_WRONLY|_O_BINARY); fptr = _fdopen(fd, "wb"); } finito: if ( !fptr ) { 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; } free(cmd_buff); return fptr; } int mingw_pclose(FILE *fp) { int i, ip, fd; pipe_data *p = NULL; DWORD ret; if ( fp == NULL ) { return -1; } /* find struct containing fd */ fd = fileno(fp); for ( i=0; imode == 'r'); CloseHandle(p->pipe[ip]); ret = WaitForSingleObject(p->piProcInfo.hProcess, INFINITE); CloseHandle(p->piProcInfo.hProcess); CloseHandle(p->piProcInfo.hThread); p->mode = '\0'; return (ret == WAIT_OBJECT_0) ? 0 : -1; }