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__ */