merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / lib / crt / process / process.c
1 #include "precomp.h"
2 #include <process.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <internal/file.h>
7 #include <tchar.h>
8
9 #define NDEBUG
10 #include <internal/debug.h>
11
12 #ifdef _UNICODE
13 #define find_execT find_execW
14 #define argvtosT argvtosW
15 #define do_spawnT do_spawnW
16 #define valisttosT valisttosW
17 #define extT extW
18 #else
19 #define find_execT find_execA
20 #define argvtosT argvtosA
21 #define do_spawnT do_spawnA
22 #define valisttosT valisttosA
23 #define extT extA
24 #endif
25
26
27 _TCHAR const* extT[] =
28 {
29 _T(""),
30 _T(".bat"),
31 _T(".cmd"),
32 _T(".com"),
33 _T(".exe")
34 };
35
36 const _TCHAR* find_execT(const _TCHAR* path, _TCHAR* rpath)
37 {
38 _TCHAR *rp;
39 const _TCHAR *rd;
40 int i, found = 0;
41
42 DPRINT(MK_STR(find_execT)"('%"sT"', %x)\n", path, rpath);
43
44 if (path == NULL)
45 {
46 return NULL;
47 }
48 if (_tcslen(path) > FILENAME_MAX - 1)
49 {
50 return path;
51 }
52 /* copy path in rpath */
53 for (rd = path, rp = rpath; *rd; *rp++ = *rd++)
54 ;
55 *rp = 0;
56 /* try first with the name as is */
57 for (i = 0; i < sizeof(extT) / sizeof(*extT); i++)
58 {
59 _tcscpy(rp, extT[i]);
60
61 DPRINT("trying '%"sT"'\n", rpath);
62
63 if (_taccess(rpath, F_OK) == 0 && access_dirT(rpath) != 0)
64 {
65 found = 1;
66 break;
67 }
68 }
69 if (!found)
70 {
71 _TCHAR* env = _tgetenv(_T("PATH"));
72 if (env)
73 {
74 _TCHAR* ep = env;
75 while (*ep && !found)
76 {
77 if (*ep == ';')
78 ep++;
79 rp=rpath;
80 for (; *ep && (*ep != ';'); *rp++ = *ep++)
81 ;
82 if (rp > rpath)
83 {
84 rp--;
85 if (*rp != '/' && *rp != '\\')
86 {
87 *++rp = '\\';
88 }
89 rp++;
90 }
91 for (rd=path; *rd; *rp++ = *rd++)
92 ;
93 for (i = 0; i < sizeof(extT) / sizeof(*extT); i++)
94 {
95 _tcscpy(rp, extT[i]);
96
97 DPRINT("trying '%"sT"'\n", rpath);
98
99 if (_taccess(rpath, F_OK) == 0 && access_dirT(rpath) != 0)
100 {
101 found = 1;
102 break;
103 }
104 }
105 }
106 }
107 }
108
109 return found ? rpath : path;
110 }
111
112 static _TCHAR*
113 argvtosT(const _TCHAR* const* argv, _TCHAR delim)
114 {
115 int i, len;
116 _TCHAR *ptr, *str;
117
118 if (argv == NULL)
119 return NULL;
120
121 for (i = 0, len = 0; argv[i]; i++)
122 {
123 len += _tcslen(argv[i]) + 1;
124 }
125
126 str = ptr = (_TCHAR*) malloc(len + 1);
127 if (str == NULL)
128 return NULL;
129
130 for(i = 0; argv[i]; i++)
131 {
132 len = _tcslen(argv[i]);
133 memcpy(ptr, argv[i], len);
134 ptr += len;
135 *ptr++ = delim;
136 }
137 *ptr = 0;
138
139 return str;
140 }
141
142 static _TCHAR*
143 valisttosT(const _TCHAR* arg0, va_list alist, _TCHAR delim)
144 {
145 va_list alist2 = alist;
146 _TCHAR *ptr, *str;
147 int len;
148
149 if (arg0 == NULL)
150 return NULL;
151
152 ptr = (_TCHAR*)arg0;
153 len = 0;
154 do
155 {
156 len += _tcslen(ptr) + 1;
157 ptr = va_arg(alist, _TCHAR*);
158 }
159 while(ptr != NULL);
160
161 str = (_TCHAR*) malloc(len + 1);
162 if (str == NULL)
163 return NULL;
164
165 ptr = str;
166 do
167 {
168 len = _tcslen(arg0);
169 memcpy(ptr, arg0, len);
170 ptr += len;
171 *ptr++ = delim;
172 arg0 = va_arg(alist2, _TCHAR*);
173 }
174 while(arg0 != NULL);
175 *ptr = 0;
176
177 return str;
178 }
179
180 static int
181 do_spawnT(int mode, const _TCHAR* cmdname, const _TCHAR* args, const _TCHAR* envp)
182 {
183 STARTUPINFO StartupInfo = {0};
184 PROCESS_INFORMATION ProcessInformation;
185 // char* fmode;
186 // HANDLE* hFile;
187 // int i, last;
188 BOOL bResult;
189 DWORD dwExitCode;
190 DWORD dwError;
191
192 TRACE(MK_STR(do_spawnT)"(%i,'%"sT"','%"sT"','%"sT"')",mode,cmdname,args,envp);
193
194
195 if (mode != _P_NOWAIT && mode != _P_NOWAITO && mode != _P_WAIT && mode != _P_DETACH && mode != _P_OVERLAY)
196 {
197 __set_errno ( EINVAL );
198 return( -1);
199 }
200
201 if (0 != _taccess(cmdname, F_OK))
202 {
203 __set_errno ( ENOENT );
204 return(-1);
205 }
206 if (0 == access_dirT(cmdname))
207 {
208 __set_errno ( EISDIR );
209 return(-1);
210 }
211
212 //memset (&StartupInfo, 0, sizeof(StartupInfo));
213 StartupInfo.cb = sizeof(StartupInfo);
214
215 #if 0
216
217 for (last = i = 0; i < FDINFO_FD_MAX; i++)
218 {
219 if ((void*)-1 != _get_osfhandle(i))
220 {
221 last = i + 1;
222 }
223 }
224
225 if (last)
226 {
227 StartupInfo.cbReserved2 = sizeof(ULONG) + last * (sizeof(char) + sizeof(HANDLE));
228 StartupInfo.lpReserved2 = malloc(StartupInfo.cbReserved2);
229 if (StartupInfo.lpReserved2 == NULL)
230 {
231 __set_errno ( ENOMEM );
232 return -1;
233 }
234
235 *(DWORD*)StartupInfo.lpReserved2 = last;
236 fmode = (char*)(StartupInfo.lpReserved2 + sizeof(ULONG));
237 hFile = (HANDLE*)(StartupInfo.lpReserved2 + sizeof(ULONG) + last * sizeof(char));
238 for (i = 0; i < last; i++)
239 {
240 int _mode = __fileno_getmode(i);
241 HANDLE h = _get_osfhandle(i);
242 /* FIXME: The test of console handles (((ULONG)Handle) & 0x10000003) == 0x3)
243 * is possible wrong
244 */
245 if ((((ULONG)h) & 0x10000003) == 0x3 || _mode & _O_NOINHERIT || (i < 3 && mode == _P_DETACH))
246 {
247 *hFile = INVALID_HANDLE_VALUE;
248 *fmode = 0;
249 }
250 else
251 {
252 DWORD dwFlags;
253 BOOL bFlag;
254 bFlag = GetHandleInformation(h, &dwFlags);
255 if (bFlag && (dwFlags & HANDLE_FLAG_INHERIT))
256 {
257 *hFile = h;
258 *fmode = (_O_ACCMODE & _mode) | (((_O_TEXT | _O_BINARY) & _mode) >> 8);
259 }
260 else
261 {
262 *hFile = INVALID_HANDLE_VALUE;
263 *fmode = 0;
264 }
265 }
266 fmode++;
267 hFile++;
268 }
269 }
270 #endif
271
272 create_io_inherit_block((STARTUPINFOA*) &StartupInfo);
273
274 bResult = CreateProcess((_TCHAR *)cmdname,
275 (_TCHAR *)args,
276 NULL,
277 NULL,
278 TRUE,
279 mode == _P_DETACH ? DETACHED_PROCESS : 0,
280 (LPVOID)envp,
281 NULL,
282 &StartupInfo,
283 &ProcessInformation);
284
285 if (StartupInfo.lpReserved2)
286 {
287 free(StartupInfo.lpReserved2);
288 }
289
290 if (!bResult)
291 {
292 dwError = GetLastError();
293 DPRINT("%x\n", dwError);
294 __set_errno(dwError);
295 return(-1);
296 }
297 CloseHandle(ProcessInformation.hThread);
298 switch(mode)
299 {
300 case _P_NOWAIT:
301 case _P_NOWAITO:
302 CloseHandle(ProcessInformation.hThread);
303 return((int)ProcessInformation.hProcess);
304 case _P_OVERLAY:
305 _exit(0);
306 case _P_WAIT:
307 WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
308 GetExitCodeProcess(ProcessInformation.hProcess, &dwExitCode);
309 CloseHandle(ProcessInformation.hProcess);
310 CloseHandle(ProcessInformation.hThread);
311 return( (int)dwExitCode); //CORRECT?
312 case _P_DETACH:
313 CloseHandle(ProcessInformation.hProcess);
314 CloseHandle(ProcessInformation.hThread);
315 return( 0);
316 }
317 return( (int)ProcessInformation.hProcess);
318 }
319
320 /*
321 * @implemented
322 */
323 int _tspawnl(int mode, const _TCHAR *cmdname, const _TCHAR* arg0, ...)
324 {
325 va_list argp;
326 _TCHAR* args;
327 int ret = -1;
328
329 DPRINT(MK_STR(_tspawnl)"('%"sT"')\n", cmdname);
330
331 va_start(argp, arg0);
332 args = valisttosT(arg0, argp, ' ');
333
334 if (args)
335 {
336 ret = do_spawnT(mode, cmdname, args, NULL);
337 free(args);
338 }
339 return ret;
340 }
341
342 /*
343 * @implemented
344 */
345 int _tspawnv(int mode, const _TCHAR *cmdname, const _TCHAR* const* argv)
346 {
347 _TCHAR* args;
348 int ret = -1;
349
350 DPRINT(MK_STR(_tspawnv)"('%"sT"')\n", cmdname);
351
352 args = argvtosT(argv, ' ');
353
354 if (args)
355 {
356 ret = do_spawnT(mode, cmdname, args, NULL);
357 free(args);
358 }
359 return ret;
360 }
361
362 /*
363 * @implemented
364 */
365 int _tspawnle(int mode, const _TCHAR *cmdname, const _TCHAR* arg0, ... /*, NULL, const char* const* envp*/)
366 {
367 va_list argp;
368 _TCHAR* args;
369 _TCHAR* envs;
370 _TCHAR const * const* ptr;
371 int ret = -1;
372
373 DPRINT(MK_STR(_tspawnle)"('%"sT"')\n", cmdname);
374
375 va_start(argp, arg0);
376 args = valisttosT(arg0, argp, ' ');
377 do
378 {
379 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
380 }
381 while (ptr != NULL);
382 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
383 envs = argvtosT(ptr, 0);
384 if (args)
385 {
386 ret = do_spawnT(mode, cmdname, args, envs);
387 free(args);
388 }
389 if (envs)
390 {
391 free(envs);
392 }
393 return ret;
394
395 }
396
397 /*
398 * @implemented
399 */
400 int _tspawnve(int mode, const _TCHAR *cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
401 {
402 _TCHAR *args;
403 _TCHAR *envs;
404 int ret = -1;
405
406 DPRINT(MK_STR(_tspawnve)"('%"sT"')\n", cmdname);
407
408 args = argvtosT(argv, ' ');
409 envs = argvtosT(envp, 0);
410
411 if (args)
412 {
413 ret = do_spawnT(mode, cmdname, args, envs);
414 free(args);
415 }
416 if (envs)
417 {
418 free(envs);
419 }
420 return ret;
421 }
422
423 /*
424 * @implemented
425 */
426 int _tspawnvp(int mode, const _TCHAR* cmdname, const _TCHAR* const* argv)
427 {
428 _TCHAR pathname[FILENAME_MAX];
429
430 DPRINT(MK_STR(_tspawnvp)"('%"sT"')\n", cmdname);
431
432 return _tspawnv(mode, find_execT(cmdname, pathname), argv);
433 }
434
435 /*
436 * @implemented
437 */
438 int _tspawnlp(int mode, const _TCHAR* cmdname, const _TCHAR* arg0, .../*, NULL*/)
439 {
440 va_list argp;
441 _TCHAR* args;
442 int ret = -1;
443 _TCHAR pathname[FILENAME_MAX];
444
445 DPRINT(MK_STR(_tspawnlp)"('%"sT"')\n", cmdname);
446
447 va_start(argp, arg0);
448 args = valisttosT(arg0, argp, ' ');
449 if (args)
450 {
451 ret = do_spawnT(mode, find_execT(cmdname, pathname), args, NULL);
452 free(args);
453 }
454 return ret;
455 }
456
457
458 /*
459 * @implemented
460 */
461 int _tspawnlpe(int mode, const _TCHAR* cmdname, const _TCHAR* arg0, .../*, NULL, const char* const* envp*/)
462 {
463 va_list argp;
464 _TCHAR* args;
465 _TCHAR* envs;
466 _TCHAR const* const * ptr;
467 int ret = -1;
468 _TCHAR pathname[FILENAME_MAX];
469
470 DPRINT(MK_STR(_tspawnlpe)"('%"sT"')\n", cmdname);
471
472 va_start(argp, arg0);
473 args = valisttosT(arg0, argp, ' ');
474 do
475 {
476 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
477 }
478 while (ptr != NULL);
479 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
480 envs = argvtosT(ptr, 0);
481 if (args)
482 {
483 ret = do_spawnT(mode, find_execT(cmdname, pathname), args, envs);
484 free(args);
485 }
486 if (envs)
487 {
488 free(envs);
489 }
490 return ret;
491 }
492
493 /*
494 * @implemented
495 */
496 int _tspawnvpe(int mode, const _TCHAR* cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
497 {
498 _TCHAR pathname[FILENAME_MAX];
499
500 DPRINT(MK_STR(_tspawnvpe)"('%"sT"')\n", cmdname);
501
502 return _tspawnve(mode, find_execT(cmdname, pathname), argv, envp);
503 }
504
505 /*
506 * @implemented
507 */
508 int _texecl(const _TCHAR* cmdname, const _TCHAR* arg0, ...)
509 {
510 _TCHAR* args;
511 va_list argp;
512 int ret = -1;
513
514 DPRINT(MK_STR(_texecl)"('%"sT"')\n", cmdname);
515
516 va_start(argp, arg0);
517 args = valisttosT(arg0, argp, ' ');
518
519 if (args)
520 {
521 ret = do_spawnT(P_OVERLAY, cmdname, args, NULL);
522 free(args);
523 }
524 return ret;
525 }
526
527 /*
528 * @implemented
529 */
530 int _texecv(const _TCHAR* cmdname, const _TCHAR* const* argv)
531 {
532 DPRINT(MK_STR(_texecv)"('%"sT"')\n", cmdname);
533 return _tspawnv(P_OVERLAY, cmdname, argv);
534 }
535
536 /*
537 * @implemented
538 */
539 int _texecle(const _TCHAR* cmdname, const _TCHAR* arg0, ... /*, NULL, char* const* envp */)
540 {
541 va_list argp;
542 _TCHAR* args;
543 _TCHAR* envs;
544 _TCHAR const* const* ptr;
545 int ret = -1;
546
547 DPRINT(MK_STR(_texecle)"('%"sT"')\n", cmdname);
548
549 va_start(argp, arg0);
550 args = valisttosT(arg0, argp, ' ');
551 do
552 {
553 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
554 }
555 while (ptr != NULL);
556 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
557 envs = argvtosT(ptr, 0);
558 if (args)
559 {
560 ret = do_spawnT(P_OVERLAY, cmdname, args, envs);
561 free(args);
562 }
563 if (envs)
564 {
565 free(envs);
566 }
567 return ret;
568 }
569
570 /*
571 * @implemented
572 */
573 int _texecve(const _TCHAR* cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
574 {
575 DPRINT(MK_STR(_texecve)"('%"sT"')\n", cmdname);
576 return _tspawnve(P_OVERLAY, cmdname, argv, envp);
577 }
578
579 /*
580 * @implemented
581 */
582 int _texeclp(const _TCHAR* cmdname, const _TCHAR* arg0, ...)
583 {
584 _TCHAR* args;
585 va_list argp;
586 int ret = -1;
587 _TCHAR pathname[FILENAME_MAX];
588
589 DPRINT(MK_STR(_texeclp)"('%"sT"')\n", cmdname);
590
591 va_start(argp, arg0);
592 args = valisttosT(arg0, argp, ' ');
593
594 if (args)
595 {
596 ret = do_spawnT(P_OVERLAY, find_execT(cmdname, pathname), args, NULL);
597 free(args);
598 }
599 return ret;
600 }
601
602 /*
603 * @implemented
604 */
605 int _texecvp(const _TCHAR* cmdname, const _TCHAR* const* argv)
606 {
607 DPRINT(MK_STR(_texecvp)"('%"sT"')\n", cmdname);
608 return _tspawnvp(P_OVERLAY, cmdname, argv);
609 }
610
611 /*
612 * @implemented
613 */
614 int _texeclpe(const _TCHAR* cmdname, const _TCHAR* arg0, ... /*, NULL, char* const* envp */)
615 {
616 va_list argp;
617 _TCHAR* args;
618 _TCHAR* envs;
619 _TCHAR const* const* ptr;
620 int ret = -1;
621 _TCHAR pathname[FILENAME_MAX];
622
623 DPRINT(MK_STR(_texeclpe)"('%"sT"')\n", cmdname);
624
625 va_start(argp, arg0);
626 args = valisttosT(arg0, argp, ' ');
627 do
628 {
629 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
630 }
631 while (ptr != NULL);
632 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
633 envs = argvtosT(ptr, 0);
634 if (args)
635 {
636 ret = do_spawnT(P_OVERLAY, find_execT(cmdname, pathname), args, envs);
637 free(args);
638 }
639 if (envs)
640 {
641 free(envs);
642 }
643 return ret;
644 }
645
646 /*
647 * @implemented
648 */
649 int _texecvpe(const _TCHAR* cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
650 {
651 DPRINT(MK_STR(_texecvpe)"('%"sT"')\n", cmdname);
652 return _tspawnvpe(P_OVERLAY, cmdname, argv, envp);
653 }
654