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