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