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