16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
|
*******************************************************************************
**
** This file contains an implementation of a bi-directional popen().
*/
#include "config.h"
#include "popen.h"
#ifdef __MINGW32__
/*
** Print a fatal error and quit.
*/
static void win32_fatal_error(const char *zMsg){
fossil_fatal("%s");
}
#endif
#ifdef __MINGW32__
/*
** On windows, create a child process and specify the stdin, stdout,
** and stderr channels for that process to use.
**
** Return the number of errors.
*/
static int win32_create_child_process(
char *zCmd, /* The command that the child process will run */
HANDLE hIn, /* Standard input */
HANDLE hOut, /* Standard output */
HANDLE hErr, /* Standard error */
DWORD *pChildPid /* OUT: Child process handle */
){
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL rc;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
SetHandleInformation(hIn, HANDLE_FLAG_INHERIT, TRUE);
si.hStdInput = hIn;
SetHandleInformation(hOut, HANDLE_FLAG_INHERIT, TRUE);
si.hStdOutput = hOut;
SetHandleInformation(hErr, HANDLE_FLAG_INHERIT, TRUE);
si.hStdError = hErr;
rc = CreateProcess(
NULL, /* Application Name */
zCmd, /* Command-line */
NULL, /* Process attributes */
NULL, /* Thread attributes */
TRUE, /* Inherit Handles */
0, /* Create flags */
NULL, /* Environment */
NULL, /* Current directory */
&si, /* Startup Info */
&pi /* Process Info */
);
if( rc ){
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
*pChildPid = pi.dwProcessId;
}else{
win32_fatal_error("cannot create child process");
}
return rc!=0;
}
#endif
/*
** Create a child process running shell command "zCmd". *ppOut is
** a FILE that becomes the standard input of the child process.
** (The caller writes to *ppOut in order to send text to the child.)
** *ppIn is stdout from the child process. (The caller
** reads from *ppIn in order to receive input from the child.)
** Note that *ppIn is an unbuffered file descriptor, not a FILE.
** The process ID of the child is written into *pChildPid.
**
** Return the number of errors.
*/
int popen2(const char *zCmd, int *pfdIn, FILE **ppOut, int *pChildPid){
#ifdef __MINGW32__
HANDLE hStdinRd, hStdinWr, hStdoutRd, hStdoutWr, hStderr;
SECURITY_ATTRIBUTES saAttr;
DWORD childPid;
int fd;
saAttr.nLength = sizeof(saAttr);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
hStderr = GetStdHandle(STD_ERROR_HANDLE);
if( !CreatePipe(&hStdoutRd, &hStdoutWr, &saAttr, 4096) ){
win32_fatal_error("cannot create pipe for stdout");
}
SetHandleInformation( hStdoutRd, HANDLE_FLAG_INHERIT, FALSE);
if( !CreatePipe(&hStdinRd, &hStdinWr, &saAttr, 4096) ){
win32_fatal_error("cannot create pipe for stdin");
}
SetHandleInformation( hStdinWr, HANDLE_FLAG_INHERIT, FALSE);
win32_create_child_process((char*)zCmd,
hStdinRd, hStdoutWr, hStderr,&childPid);
*pChildPid = childPid;
*pfdIn = _open_osfhandle(hStdoutRd, 0);
fd = _open_osfhandle(hStdoutWr, 0);
*ppOut = _fdopen(fd, "w");
CloseHandle(hStdinRd);
CloseHandle(hStdoutWr);
return 1; /* Not implemented on windows, yet */
return 0;
#else
int pin[2], pout[2];
*pfdIn = 0;
*ppOut = 0;
*pChildPid = 0;
if( pipe(pin)<0 ){
|