Overview
Artifact ID: | ca27aac2bf8e9a941dfbc2a7b4c15ae0de87f59b |
---|---|
Ticket: | 11622724e5b46818396db583ac839391f70c8d64 |
Date: | 2010-08-26 09:04:55 |
User: | anonymous |
Artifact Attached: | d2dbbd685c4b68cc142df74c4fb2f73486a642e1 |
Filename: | my_popen.h |
Description: | subroutine "popen2" on win32. |
Content Appended
1 #if defined(__MINGW32__) 2 #include <sys/fcntl.h> 3 #include <tchar.h> 4 #include <windows.h> 5 6 /* 7 * Display the error message of Windows system call 8 */ 9 void ErrorExit(LPTSTR lpszFunction) 10 { 11 /* Retrieve the system error message for the last-error code */ 12 TCHAR buff[1024] = {}; 13 DWORD dw = GetLastError(); 14 15 FormatMessage( 16 FORMAT_MESSAGE_FROM_SYSTEM | 17 FORMAT_MESSAGE_IGNORE_INSERTS, 18 NULL, 19 dw, 20 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 21 &buff, 22 sizeof(buff)/sizeof(buff[0]), 23 NULL ); 24 25 /* Display the error message and exit the process */ 26 _ftprintf(stderr, "%s\n%s\n", buff, lpszFunction); 27 28 ExitProcess(dw); 29 } 30 31 /* 32 * Convert a Windows file handle to crt type FILE* 33 */ 34 FILE* fhopen(HANDLE hFile, const char *zMode){ 35 int fd = _open_osfhandle((intptr_t)hFile, _O_BINARY); 36 37 if( fd != -1) 38 return _fdopen(fd, zMode); 39 else 40 return NULL; 41 } 42 43 44 /* 45 * Spawn child process and redirect its io to our handles 46 */ 47 static DWORD SpawnChild(LPTSTR lpCmdLine, HANDLE hIn, HANDLE hOut, HANDLE hErr) 48 { 49 STARTUPINFO si; 50 PROCESS_INFORMATION pi; 51 BOOL success; 52 53 memset((void *)&si, 0, sizeof(STARTUPINFO)); 54 si.cb = sizeof (STARTUPINFO); 55 56 /* 57 * Indicate the hStdInput, hStdOutput, and hStdError members are valid. 58 */ 59 si.dwFlags = STARTF_USESTDHANDLES; 60 61 si.hStdInput = hIn; 62 si.hStdOutput = hOut; 63 si.hStdError = hErr; 64 65 /* 66 * Ensure stdio inheritable. 67 */ 68 success = SetHandleInformation(si.hStdInput, HANDLE_FLAG_INHERIT, TRUE); 69 if(!success) { 70 ErrorExit("SetHandleInformation failed"); 71 } 72 73 success = SetHandleInformation(si.hStdOutput, HANDLE_FLAG_INHERIT, TRUE); 74 if(!success) { 75 ErrorExit("SetHandleInformation failed"); 76 } 77 78 success = SetHandleInformation(si.hStdError, HANDLE_FLAG_INHERIT, TRUE); 79 if(!success) { 80 ErrorExit("SetHandleInformation failed"); 81 } 82 83 /* 84 * Create child process 85 */ 86 success = CreateProcess(NULL, /* LPCSTR address of module name */ 87 lpCmdLine, /* LPCSTR address of command line */ 88 NULL, /* Process security attributes */ 89 NULL, /* Thread security attributes */ 90 TRUE, /* Inheritable Handes inherited. */ 91 0, /* DWORD creation flags */ 92 NULL, /* Use parent environment block */ 93 NULL, /* Address of current directory name */ 94 &si, /* Address of STARTUPINFO */ 95 &pi); /* Address of PROCESS_INFORMATION */ 96 97 if(!success){ 98 ErrorExit("CreateProcess failed"); 99 } 100 101 /* Close process and thread handles. */ 102 CloseHandle( pi.hProcess ); 103 CloseHandle( pi.hThread ); 104 105 return pi.dwProcessId; 106 } 107 108 static DWORD win32_create_child(const char *zCmd, HANDLE *hIn, HANDLE *hOut) 109 { 110 HANDLE hChildStdinRd, hChildStdinWr, 111 hChildStdoutRd, hChildStdoutWr; 112 HANDLE hStderr; 113 114 SECURITY_ATTRIBUTES saAttr; 115 BOOL fSuccess; 116 117 118 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 119 saAttr.bInheritHandle = TRUE; /* Set the bInheritHandle flag so pipe handles are inherited. */ 120 saAttr.lpSecurityDescriptor = NULL; 121 122 #if defined(FOSSIL_CHILD_DEBUG) 123 char zDebugFName[200] = {0}; 124 const char *zTempPrefix = "sever_child_debug_output"; 125 126 static volatile long i = 0; 127 128 InterlockedIncrement(&i); 129 130 snprintf(zDebugFName, sizeof(zDebugFName), "%s_%05ld.txt", zTempPrefix, i); 131 132 hStderr = CreateFile(zDebugFName, // file to open 133 GENERIC_WRITE, // open for reading 134 FILE_SHARE_READ, // share for reading 135 NULL, // default security 136 CREATE_ALWAYS, // existing file only 137 FILE_ATTRIBUTE_NORMAL, // normal file 138 NULL); // no attr. template 139 140 SetHandleInformation( hStderr, HANDLE_FLAG_INHERIT, TRUE); 141 #else 142 /* Get the handle to the current STDERR. */ 143 hStderr = GetStdHandle(STD_ERROR_HANDLE); 144 #endif 145 146 /* Create a pipe for the child process's STDOUT. */ 147 if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 4096)) 148 ErrorExit("Stdout pipe creation failed\n"); 149 150 /* Ensure the read handle to the pipe for STDOUT is not inherited. */ 151 SetHandleInformation( hChildStdoutRd, HANDLE_FLAG_INHERIT, FALSE); 152 153 /* Create a pipe for the child process's STDIN. */ 154 if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 4096)) 155 ErrorExit("Stdin pipe creation failed\n"); 156 157 /* Ensure the write handle to the pipe for STDIN is not inherited. */ 158 SetHandleInformation( hChildStdinWr, HANDLE_FLAG_INHERIT, FALSE); 159 160 /* Spawn child and redirect its io */ 161 DWORD processId = SpawnChild(zCmd, hChildStdinRd, hChildStdoutWr, hStderr); 162 163 /* Close pipe handles that used by child to read and write */ 164 CloseHandle(hChildStdinRd); 165 CloseHandle(hChildStdoutWr); 166 #if defined(FOSSIL_CHILD_DEBUG) 167 CloseHandle(hStderr); 168 #endif 169 170 *hIn = hChildStdoutRd; 171 *hOut = hChildStdinWr; 172 173 return processId; 174 } 175 176 int popen2(const char *zCmd, FILE **ppIn, FILE **ppOut, int *pChildPid){ 177 HANDLE in, out; 178 DWORD childProcessId = win32_create_child(zCmd, &in, &out); 179 180 if(childProcessId == 0){ 181 fossil_fatal("create child process failed"); 182 } 183 184 *ppIn = fhopen(in, "rb"); 185 *ppOut = fhopen(out, "wb"); 186 187 if( (*ppIn) == NULL || (*ppOut) == NULL){ 188 fossil_fatal("fhopen failed!"); 189 } 190 191 *pChildPid = childProcessId; 192 } 193 #endif /* __MINGW32__ */