b6195d0a6a4e67f2da733dbba008f09cff7bb023
[reactos.git] / reactos / base / shell / cmd / start.c
1 /*
2 * START.C - start internal command.
3 *
4 *
5 * History:
6 *
7 * 24-Jul-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
8 * Started.
9 *
10 * 30-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>)
11 * Remove all hardcode string to En.rc
12 */
13
14 #include <precomp.h>
15 #include "resource.h"
16
17 #ifdef INCLUDE_CMD_START
18
19
20 INT cmd_start (LPTSTR First, LPTSTR Rest)
21 {
22 TCHAR szFullName[CMDLINE_LENGTH];
23 TCHAR first[CMDLINE_LENGTH];
24 TCHAR *rest = NULL;
25 TCHAR *param = NULL;
26 TCHAR RestWithoutArgs[CMDLINE_LENGTH];
27 INT size;
28 LPTSTR comspec;
29 BOOL bWait = FALSE;
30 BOOL bBat = FALSE;
31 BOOL bCreate = FALSE;
32 TCHAR szFullCmdLine [CMDLINE_LENGTH];
33 PROCESS_INFORMATION prci;
34 STARTUPINFO stui;
35 LPTSTR *arg;
36 INT argc = 0;
37 INT i = 0;
38 DWORD Priority = 0;
39
40 RestWithoutArgs[0] = _T('\0');
41 _tcscpy(first,First);
42 arg = split (Rest, &argc, FALSE);
43
44
45 for (i = 0; i < argc; i++)
46 {
47 if (!_tcsncmp (arg[i], _T("/?"), 2))
48 {
49 freep(arg);
50 ConOutResPaging(TRUE,STRING_START_HELP1);
51 return 0;
52 }
53 else if(!_tcsicmp(arg[i], "/LOW"))
54 {
55 Priority = IDLE_PRIORITY_CLASS;
56 }
57 else if(!_tcsicmp(arg[i], "/NORMAL"))
58 {
59 Priority = NORMAL_PRIORITY_CLASS;
60 }
61 else if(!_tcsicmp(arg[i], "/HIGH"))
62 {
63 Priority = HIGH_PRIORITY_CLASS;
64 }
65 else if(!_tcsicmp(arg[i], "/REALTIME"))
66 {
67 Priority = REALTIME_PRIORITY_CLASS;
68 }
69 else if(!_tcsicmp(arg[i], "/ABOVENORMAL"))
70 {
71 Priority = ABOVE_NORMAL_PRIORITY_CLASS;
72 }
73 else if(!_tcsicmp(arg[i], "/BELOWNORMAL"))
74 {
75 Priority = BELOW_NORMAL_PRIORITY_CLASS;
76 }
77 else
78 {
79 if(RestWithoutArgs[0] != _T('\0'))
80 {
81 _tcscat(RestWithoutArgs,_T(" "));
82 }
83 _tcscat(RestWithoutArgs,arg[i]);
84 }
85 }
86
87
88
89
90 freep (arg);
91
92 /* get comspec */
93 comspec = malloc ( MAX_PATH * sizeof(TCHAR));
94 if (comspec == NULL)
95 {
96 error_out_of_memory();
97 return 1;
98 }
99 SetLastError(0);
100 size = GetEnvironmentVariable (_T("COMSPEC"), comspec, 512);
101 if(GetLastError() == ERROR_ENVVAR_NOT_FOUND)
102 {
103 RestWithoutArgs[0] = _T('c');
104 RestWithoutArgs[1] = _T('m');
105 RestWithoutArgs[2] = _T('d');
106 RestWithoutArgs[3] = _T('\0');
107 }
108 else
109 {
110 if (size > MAX_PATH)
111 {
112 comspec = realloc(comspec,size * sizeof(TCHAR) );
113 if (comspec==NULL)
114 {
115 return 1;
116 }
117 size = GetEnvironmentVariable (_T("COMSPEC"), comspec, size);
118 }
119 }
120
121 nErrorLevel = 0;
122
123 if(!_tcslen(RestWithoutArgs))
124 {
125 _tcscpy(RestWithoutArgs,_T("\""));
126 _tcscat(RestWithoutArgs,comspec);
127 _tcscat(RestWithoutArgs,_T("\""));
128 }
129
130 rest = malloc ( _tcslen(RestWithoutArgs) + 1 * sizeof(TCHAR));
131 if (rest == NULL)
132 {
133 if(comspec != NULL)
134 free(comspec);
135 error_out_of_memory();
136 return 1;
137 }
138
139 param =malloc ( _tcslen(RestWithoutArgs) + 1 * sizeof(TCHAR));
140 if (rest == NULL)
141 {
142 if(comspec != NULL)
143 free(comspec);
144 free(rest);
145 error_out_of_memory();
146 return 1;
147 }
148
149 param[0] = _T('\0');
150
151
152 _tcscpy(rest,RestWithoutArgs);
153
154 /* Parsing the command that gets called by start, and it's parameters */
155 if(!_tcschr(rest,_T('\"')))
156 {
157 INT count = _tcslen(rest);
158
159 /* find the end of the command and start of the args */
160 for(i = 0; i < count; i++)
161 {
162 if(rest[i] == _T(' '))
163 {
164
165 _tcscpy(param,&rest[i+1]);
166 rest[i] = _T('\0');
167 break;
168 }
169 }
170 }
171 else
172 {
173 INT count = _tcslen(rest);
174 BOOL bInside = FALSE;
175
176 /* find the end of the command and put the arguments in param */
177 for(i = 0; i < count; i++)
178 {
179 if(rest[i] == _T('\"'))
180 bInside = !bInside;
181 if((rest[i] == _T(' ')) && !bInside)
182 {
183 _tcscpy(param,&rest[i+1]);
184 rest[i] = _T('\0');
185 break;
186 }
187 }
188 i = 0;
189 /* remove any slashes */
190 while(i < count)
191 {
192 if(rest[i] == _T('\"'))
193 memmove(&rest[i],&rest[i + 1], _tcslen(&rest[i]) * sizeof(TCHAR));
194 else
195 i++;
196 }
197 }
198
199 /* check for a drive change */
200
201 if (!_tcscmp (first + 1, _T(":")) && _istalpha (*first))
202 {
203 TCHAR szPath[CMDLINE_LENGTH];
204
205 _tcscpy (szPath, _T("A:"));
206 szPath[0] = _totupper (*first);
207 SetCurrentDirectory (szPath);
208 GetCurrentDirectory (CMDLINE_LENGTH, szPath);
209 if (szPath[0] != (TCHAR)_totupper (*first))
210 ConErrResPuts (STRING_FREE_ERROR1);
211
212 if (rest != NULL)
213 free(rest);
214
215 if (param != NULL)
216 free(param);
217 if (comspec != NULL)
218 free(comspec);
219 return 0;
220 }
221
222 /* get the PATH environment variable and parse it */
223 /* search the PATH environment variable for the binary */
224 if (!SearchForExecutable (rest, szFullName))
225 {
226 error_bad_command ();
227
228 if (rest != NULL)
229 free(rest);
230
231 if (param != NULL)
232 free(param);
233
234 if (comspec != NULL)
235 free(comspec);
236 return 1;
237 }
238
239
240 /* check if this is a .BAT or .CMD file */
241 if (!_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".bat")) ||
242 !_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".cmd")))
243 {
244 bBat = TRUE;
245 memset(szFullCmdLine,0,CMDLINE_LENGTH * sizeof(TCHAR));
246
247
248 _tcscpy(szFullCmdLine,comspec);
249
250 memcpy(&szFullCmdLine[_tcslen(szFullCmdLine)],_T("\" /K \""), 6 * sizeof(TCHAR));
251 memcpy(&szFullCmdLine[_tcslen(szFullCmdLine)], szFullName, _tcslen(szFullName) * sizeof(TCHAR));
252 memcpy(&szFullCmdLine[1], &szFullCmdLine[0], _tcslen(szFullCmdLine) * sizeof(TCHAR));
253 szFullCmdLine[0] = _T('\"');
254 szFullCmdLine[_tcslen(szFullCmdLine)] = _T('\"');
255 }
256
257 #ifdef _DEBUG
258 DebugPrintf (_T("[BATCH: %s %s]\n"), szFullName, rest);
259 #endif
260
261
262 #ifdef _DEBUG
263 DebugPrintf (_T("[EXEC: %s %s]\n"), szFullName, rest);
264 #endif
265 /* build command line for CreateProcess() */
266 if (bBat == FALSE)
267 {
268 _tcscpy (szFullCmdLine, first);
269 if( param != NULL )
270 {
271
272 _tcscat(szFullCmdLine, _T(" ") );
273 _tcscat (szFullCmdLine, param);
274 }
275 }
276
277 /* fill startup info */
278 memset (&stui, 0, sizeof (STARTUPINFO));
279 stui.cb = sizeof (STARTUPINFO);
280 stui.dwFlags = STARTF_USESHOWWINDOW;
281 stui.wShowWindow = SW_SHOWDEFAULT;
282
283 if (bBat == TRUE)
284 {
285 bCreate = CreateProcess (NULL, szFullCmdLine, NULL, NULL, FALSE,
286 CREATE_NEW_CONSOLE | Priority, NULL, NULL, &stui, &prci);
287 }
288 else
289 {
290 bCreate = CreateProcess (szFullName, szFullCmdLine, NULL, NULL, FALSE,
291 CREATE_NEW_CONSOLE | Priority, NULL, NULL, &stui, &prci);
292 }
293
294 if (bCreate)
295 {
296 if (bWait)
297 {
298 DWORD dwExitCode;
299 WaitForSingleObject (prci.hProcess, INFINITE);
300 GetExitCodeProcess (prci.hProcess, &dwExitCode);
301 nErrorLevel = (INT)dwExitCode;
302 }
303 CloseHandle (prci.hThread);
304 CloseHandle (prci.hProcess);
305 /* Get New code page if it has change */
306 InputCodePage= GetConsoleCP();
307 OutputCodePage = GetConsoleOutputCP();
308 }
309 else
310 {
311 ErrorMessage(GetLastError (),
312 _T("Error executing CreateProcess()!!\n"));
313 }
314
315
316 if (rest != NULL)
317 free(rest);
318
319 if (param != NULL)
320 free(param);
321
322 if (comspec != NULL)
323 free(comspec);
324 return 0;
325 }
326
327 #endif
328
329 /* EOF */