2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS C runtime library
4 * FILE: lib/sdk/crt/stdio/popen.c
5 * PURPOSE: Pipe Functions
6 * PROGRAMMERS: Eric Kohl
8 * Also adapted from Wine team code by Andreas Maier.
22 int msvcrt_alloc_fd(HANDLE hand
, int flag
); //FIXME: Remove
23 unsigned split_oflags(unsigned oflags
); //FIXME: Remove
26 struct popen_handle
*popen_handles
= NULL
;
27 DWORD popen_handles_size
= 0;
29 void msvcrt_free_popen_data(void)
38 FILE *_tpopen (const _TCHAR
*cm
, const _TCHAR
*md
) /* program name, pipe mode */
40 _TCHAR
*szCmdLine
=NULL
;
41 _TCHAR
*szComSpec
=NULL
;
44 HANDLE hReadPipe
, hWritePipe
;
46 STARTUPINFO StartupInfo
;
47 PROCESS_INFORMATION ProcessInformation
;
48 SECURITY_ATTRIBUTES sa
= {sizeof(SECURITY_ATTRIBUTES
), NULL
, TRUE
};
49 struct popen_handle
*container
;
52 TRACE(MK_STR(_tpopen
)"('%"sT
"', '%"sT
"')\n", cm
, md
);
57 szComSpec
= _tgetenv(_T("COMSPEC"));
58 if (szComSpec
== NULL
)
60 szComSpec
= _T("cmd.exe");
63 s
= max(_tcsrchr(szComSpec
, '\\'), _tcsrchr(szComSpec
, '/'));
69 szCmdLine
= malloc((_tcslen(s
) + 4 + _tcslen(cm
) + 1) * sizeof(_TCHAR
));
70 if (szCmdLine
== NULL
)
75 _tcscpy(szCmdLine
, s
);
76 s
= _tcsrchr(szCmdLine
, '.');
79 _tcscat(szCmdLine
, _T(" /C "));
80 _tcscat(szCmdLine
, cm
);
82 if ( !CreatePipe(&hReadPipe
,&hWritePipe
,&sa
,1024))
88 memset(&ProcessInformation
, 0, sizeof(ProcessInformation
));
89 memset(&StartupInfo
, 0, sizeof(STARTUPINFO
));
90 StartupInfo
.cb
= sizeof(STARTUPINFO
);
93 StartupInfo
.hStdInput
= GetStdHandle(STD_INPUT_HANDLE
);
94 StartupInfo
.hStdOutput
= hWritePipe
;
95 StartupInfo
.dwFlags
|= STARTF_USESTDHANDLES
;
97 else if ( *md
== 'w' ) {
98 StartupInfo
.hStdInput
= hReadPipe
;
99 StartupInfo
.hStdOutput
= GetStdHandle(STD_OUTPUT_HANDLE
);
100 StartupInfo
.dwFlags
|= STARTF_USESTDHANDLES
;
103 if (StartupInfo
.dwFlags
& STARTF_USESTDHANDLES
)
104 StartupInfo
.hStdError
= GetStdHandle(STD_ERROR_HANDLE
);
106 result
= CreateProcess(szComSpec
,
115 &ProcessInformation
);
120 CloseHandle(hReadPipe
);
121 CloseHandle(hWritePipe
);
125 CloseHandle(ProcessInformation
.hThread
);
128 for(i
=0; i
<popen_handles_size
; i
++)
130 if (!popen_handles
[i
].f
)
133 if (i
==popen_handles_size
)
135 i
= (popen_handles_size
? popen_handles_size
*2 : 8);
136 container
= realloc(popen_handles
, i
*sizeof(*container
));
137 if (!container
) goto error
;
139 popen_handles
= container
;
140 container
= popen_handles
+popen_handles_size
;
141 memset(container
, 0, (i
-popen_handles_size
)*sizeof(*container
));
142 popen_handles_size
= i
;
144 else container
= popen_handles
+i
;
148 ret
= _tfdopen(msvcrt_alloc_fd(hReadPipe
, split_oflags(_fmode
)) , _T("r"));
149 CloseHandle(hWritePipe
);
153 ret
= _tfdopen( msvcrt_alloc_fd(hWritePipe
, split_oflags(_fmode
)) , _T("w"));
154 CloseHandle(hReadPipe
);
158 container
->proc
= ProcessInformation
.hProcess
;
159 _munlock(_POPEN_LOCK
);
164 _munlock(_POPEN_LOCK
);
165 if (ProcessInformation
.hProcess
!= 0)
166 CloseHandle(ProcessInformation
.hProcess
);
175 int CDECL
_pclose(FILE* file
)
180 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return -1;
183 for(i
=0; i
<popen_handles_size
; i
++)
185 if (popen_handles
[i
].f
== file
)
188 if(i
== popen_handles_size
)
190 _munlock(_POPEN_LOCK
);
195 h
= popen_handles
[i
].proc
;
196 popen_handles
[i
].f
= NULL
;
197 _munlock(_POPEN_LOCK
);
200 if(WaitForSingleObject(h
, INFINITE
)==WAIT_FAILED
|| !GetExitCodeProcess(h
, &i
))
202 _dosmaperr(GetLastError());