- Complete rewrite of environment variable handling to get rid of memory leaks, heap...
[reactos.git] / reactos / lib / msvcrt / stdio / popen.c
1 #include "precomp.h"
2 #include <msvcrt/io.h>
3 #include <msvcrt/errno.h>
4 #include <msvcrt/stdio.h>
5 #include <msvcrt/stdlib.h>
6 #include <msvcrt/string.h>
7 #include <msvcrt/internal/file.h>
8 #define NDEBUG
9 #include <msvcrt/msvcrtdbg.h>
10
11
12 /*
13 * @implemented
14 */
15 FILE *_popen (const char *cm, const char *md) /* program name, pipe mode */
16 {
17 char *szCmdLine=NULL;
18 char *szComSpec=NULL;
19 char *s;
20 FILE *pf;
21 HANDLE hReadPipe, hWritePipe;
22 BOOL result;
23 STARTUPINFOA StartupInfo;
24 PROCESS_INFORMATION ProcessInformation;
25 SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
26
27 DPRINT("_popen('%s', '%s')\n", cm, md);
28
29 if (cm == NULL)
30 return NULL;
31
32 szComSpec = getenv("COMSPEC");
33 if (szComSpec == NULL)
34 {
35 szComSpec = "cmd.exe";
36 }
37
38 s = max(strrchr(szComSpec, '\\'), strrchr(szComSpec, '/'));
39 if (s == NULL)
40 s = szComSpec;
41 else
42 s++;
43
44 szCmdLine = malloc(strlen(s) + 4 + strlen(cm) + 1);
45 if (szCmdLine == NULL)
46 {
47 return NULL;
48 }
49
50 strcpy(szCmdLine, s);
51 s = strrchr(szCmdLine, '.');
52 if (s)
53 *s = 0;
54 strcat(szCmdLine, " /C ");
55 strcat(szCmdLine, cm);
56
57 if ( !CreatePipe(&hReadPipe,&hWritePipe,&sa,1024))
58 {
59 free (szCmdLine);
60 return NULL;
61 }
62
63 memset(&StartupInfo, 0, sizeof(STARTUPINFOA));
64 StartupInfo.cb = sizeof(STARTUPINFOA);
65
66 if (*md == 'r' ) {
67 StartupInfo.hStdOutput = hWritePipe;
68 StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
69 }
70 else if ( *md == 'w' ) {
71 StartupInfo.hStdInput = hReadPipe;
72 StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
73 }
74
75 result = CreateProcessA(szComSpec,
76 szCmdLine,
77 NULL,
78 NULL,
79 TRUE,
80 0,
81 NULL,
82 NULL,
83 &StartupInfo,
84 &ProcessInformation);
85 free (szCmdLine);
86
87 if (result == FALSE)
88 {
89 CloseHandle(hReadPipe);
90 CloseHandle(hWritePipe);
91 return NULL;
92 }
93
94 CloseHandle(ProcessInformation.hThread);
95
96 if ( *md == 'r' )
97 {
98 pf = _fdopen(__fileno_alloc(hReadPipe, _fmode) , "r");
99 CloseHandle(hWritePipe);
100 }
101 else
102 {
103 pf = _fdopen( __fileno_alloc(hWritePipe, _fmode) , "w");
104 CloseHandle(hReadPipe);
105 }
106
107 pf->_name_to_remove = ProcessInformation.hProcess;
108
109 return pf;
110 }
111
112
113 /*
114 * @implemented
115 */
116 int _pclose (FILE *pp)
117 {
118 fclose(pp);
119 if (!TerminateProcess(pp->_name_to_remove,0))
120 return -1;
121 return 0;
122 }
123
124
125 /*
126 * @implemented
127 */
128 FILE *_wpopen (const wchar_t *cm, const wchar_t *md) /* program name, pipe mode */
129 {
130 wchar_t *szCmdLine=NULL;
131 wchar_t *szComSpec=NULL;
132 wchar_t *s;
133 FILE *pf;
134 HANDLE hReadPipe, hWritePipe;
135 BOOL result;
136 STARTUPINFOW StartupInfo;
137 PROCESS_INFORMATION ProcessInformation;
138 SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
139
140 DPRINT("_wpopen('%S', '%S')\n", cm, md);
141
142 if (cm == NULL)
143 return NULL;
144
145 szComSpec = _wgetenv(L"COMSPEC");
146
147 if (szComSpec == NULL)
148 {
149 szComSpec = L"cmd.exe";
150 }
151
152 s = max(wcsrchr(szComSpec, L'\\'), wcsrchr(szComSpec, L'/'));
153 if (s == NULL)
154 s = szComSpec;
155 else
156 s++;
157
158 szCmdLine = malloc((wcslen(s) + 4 + wcslen(cm) + 1) * sizeof(wchar_t));
159 if (szCmdLine == NULL)
160 {
161 return NULL;
162 }
163
164 wcscpy(szCmdLine, s);
165 s = wcsrchr(szCmdLine, L'.');
166 if (s)
167 *s = 0;
168 wcscat(szCmdLine, L" /C ");
169 wcscat(szCmdLine, cm);
170
171 if ( !CreatePipe(&hReadPipe,&hWritePipe,&sa,1024))
172 {
173 free (szCmdLine);
174 return NULL;
175 }
176
177 memset(&StartupInfo, 0, sizeof(STARTUPINFOW));
178 StartupInfo.cb = sizeof(STARTUPINFOW);
179
180 if (*md == L'r' ) {
181 StartupInfo.hStdOutput = hWritePipe;
182 StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
183 }
184 else if ( *md == L'w' ) {
185 StartupInfo.hStdInput = hReadPipe;
186 StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
187 }
188
189 result = CreateProcessW(szComSpec,
190 szCmdLine,
191 NULL,
192 NULL,
193 TRUE,
194 0,
195 NULL,
196 NULL,
197 &StartupInfo,
198 &ProcessInformation);
199 free (szCmdLine);
200
201 if (result == FALSE)
202 {
203 CloseHandle(hReadPipe);
204 CloseHandle(hWritePipe);
205 return NULL;
206 }
207
208 CloseHandle(ProcessInformation.hThread);
209
210 if ( *md == L'r' )
211 {
212 pf = _wfdopen(__fileno_alloc(hReadPipe, _fmode) , L"r");
213 CloseHandle(hWritePipe);
214 }
215 else
216 {
217 pf = _wfdopen( __fileno_alloc(hWritePipe, _fmode) , L"w");
218 CloseHandle(hReadPipe);
219 }
220
221 pf->_name_to_remove = ProcessInformation.hProcess;
222
223 return pf;
224 }