Ensure variables defined in $(call ...) have global scope
[make.git] / w32 / subproc / sub_proc.c
blobdcb77bf3f4670d2954fc5b8ff914d9a609f39dad
1 /* Process handling for Windows.
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4 This file is part of GNU Make.
6 GNU Make is free software; you can redistribute it and/or modify it under the
7 terms of the GNU General Public License as published by the Free Software
8 Foundation; either version 3 of the License, or (at your option) any later
9 version.
11 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along with
16 this program. If not, see <http://www.gnu.org/licenses/>. */
18 #include <config.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #ifdef _MSC_VER
22 # include <stddef.h> /* for intptr_t */
23 #else
24 # include <stdint.h>
25 #endif
26 #include <process.h> /* for msvc _beginthreadex, _endthreadex */
27 #include <signal.h>
28 #include <windows.h>
30 #include "sub_proc.h"
31 #include "proc.h"
32 #include "w32err.h"
33 #include "debug.h"
35 static char *make_command_line(char *shell_name, char *exec_path, char **argv);
36 extern char *xmalloc (unsigned int);
38 typedef struct sub_process_t {
39 intptr_t sv_stdin[2];
40 intptr_t sv_stdout[2];
41 intptr_t sv_stderr[2];
42 int using_pipes;
43 char *inp;
44 DWORD incnt;
45 char * volatile outp;
46 volatile DWORD outcnt;
47 char * volatile errp;
48 volatile DWORD errcnt;
49 pid_t pid;
50 int exit_code;
51 int signal;
52 long last_err;
53 long lerrno;
54 } sub_process;
56 /* keep track of children so we can implement a waitpid-like routine */
57 static sub_process *proc_array[MAXIMUM_WAIT_OBJECTS];
58 static int proc_index = 0;
59 static int fake_exits_pending = 0;
62 * When a process has been waited for, adjust the wait state
63 * array so that we don't wait for it again
65 static void
66 process_adjust_wait_state(sub_process* pproc)
68 int i;
70 if (!proc_index)
71 return;
73 for (i = 0; i < proc_index; i++)
74 if (proc_array[i]->pid == pproc->pid)
75 break;
77 if (i < proc_index) {
78 proc_index--;
79 if (i != proc_index)
80 memmove(&proc_array[i], &proc_array[i+1],
81 (proc_index-i) * sizeof(sub_process*));
82 proc_array[proc_index] = NULL;
87 * Waits for any of the registered child processes to finish.
89 static sub_process *
90 process_wait_for_any_private(void)
92 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
93 DWORD retval, which;
94 int i;
96 if (!proc_index)
97 return NULL;
99 /* build array of handles to wait for */
100 for (i = 0; i < proc_index; i++) {
101 handles[i] = (HANDLE) proc_array[i]->pid;
103 if (fake_exits_pending && proc_array[i]->exit_code)
104 break;
107 /* wait for someone to exit */
108 if (!fake_exits_pending) {
109 retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE);
110 which = retval - WAIT_OBJECT_0;
111 } else {
112 fake_exits_pending--;
113 retval = !WAIT_FAILED;
114 which = i;
117 /* return pointer to process */
118 if (retval != WAIT_FAILED) {
119 sub_process* pproc = proc_array[which];
120 process_adjust_wait_state(pproc);
121 return pproc;
122 } else
123 return NULL;
127 * Terminate a process.
129 BOOL
130 process_kill(HANDLE proc, int signal)
132 sub_process* pproc = (sub_process*) proc;
133 pproc->signal = signal;
134 return (TerminateProcess((HANDLE) pproc->pid, signal));
138 * Use this function to register processes you wish to wait for by
139 * calling process_file_io(NULL) or process_wait_any(). This must be done
140 * because it is possible for callers of this library to reuse the same
141 * handle for multiple processes launches :-(
143 void
144 process_register(HANDLE proc)
146 if (proc_index < MAXIMUM_WAIT_OBJECTS)
147 proc_array[proc_index++] = (sub_process *) proc;
151 * Return the number of processes that we are still waiting for.
154 process_used_slots(void)
156 return proc_index;
160 * Public function which works kind of like waitpid(). Wait for any
161 * of the children to die and return results. To call this function,
162 * you must do 1 of things:
164 * x = process_easy(...);
166 * or
168 * x = process_init_fd();
169 * process_register(x);
171 * or
173 * x = process_init();
174 * process_register(x);
176 * You must NOT then call process_pipe_io() because this function is
177 * not capable of handling automatic notification of any child
178 * death.
181 HANDLE
182 process_wait_for_any(void)
184 sub_process* pproc = process_wait_for_any_private();
186 if (!pproc)
187 return NULL;
188 else {
190 * Ouch! can't tell caller if this fails directly. Caller
191 * will have to use process_last_err()
193 (void) process_file_io(pproc);
194 return ((HANDLE) pproc);
198 long
199 process_signal(HANDLE proc)
201 if (proc == INVALID_HANDLE_VALUE) return 0;
202 return (((sub_process *)proc)->signal);
205 long
206 process_last_err(HANDLE proc)
208 if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
209 return (((sub_process *)proc)->last_err);
212 long
213 process_exit_code(HANDLE proc)
215 if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE;
216 return (((sub_process *)proc)->exit_code);
220 2006-02:
221 All the following functions are currently unused.
222 All of them would crash gmake if called with argument INVALID_HANDLE_VALUE.
223 Hence whoever wants to use one of this functions must invent and implement
224 a reasonable error handling for this function.
226 char *
227 process_outbuf(HANDLE proc)
229 return (((sub_process *)proc)->outp);
232 char *
233 process_errbuf(HANDLE proc)
235 return (((sub_process *)proc)->errp);
239 process_outcnt(HANDLE proc)
241 return (((sub_process *)proc)->outcnt);
245 process_errcnt(HANDLE proc)
247 return (((sub_process *)proc)->errcnt);
250 void
251 process_pipes(HANDLE proc, int pipes[3])
253 pipes[0] = ((sub_process *)proc)->sv_stdin[0];
254 pipes[1] = ((sub_process *)proc)->sv_stdout[0];
255 pipes[2] = ((sub_process *)proc)->sv_stderr[0];
256 return;
260 HANDLE
261 process_init()
263 sub_process *pproc;
265 * open file descriptors for attaching stdin/stdout/sterr
267 HANDLE stdin_pipes[2];
268 HANDLE stdout_pipes[2];
269 HANDLE stderr_pipes[2];
270 SECURITY_ATTRIBUTES inherit;
271 BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
273 pproc = malloc(sizeof(*pproc));
274 memset(pproc, 0, sizeof(*pproc));
276 /* We can't use NULL for lpSecurityDescriptor because that
277 uses the default security descriptor of the calling process.
278 Instead we use a security descriptor with no DACL. This
279 allows nonrestricted access to the associated objects. */
281 if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),
282 SECURITY_DESCRIPTOR_REVISION)) {
283 pproc->last_err = GetLastError();
284 pproc->lerrno = E_SCALL;
285 return((HANDLE)pproc);
288 inherit.nLength = sizeof(inherit);
289 inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);
290 inherit.bInheritHandle = TRUE;
292 // By convention, parent gets pipe[0], and child gets pipe[1]
293 // This means the READ side of stdin pipe goes into pipe[1]
294 // and the WRITE side of the stdout and stderr pipes go into pipe[1]
295 if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||
296 CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||
297 CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {
299 pproc->last_err = GetLastError();
300 pproc->lerrno = E_SCALL;
301 return((HANDLE)pproc);
305 // Mark the parent sides of the pipes as non-inheritable
307 if (SetHandleInformation(stdin_pipes[0],
308 HANDLE_FLAG_INHERIT, 0) == FALSE ||
309 SetHandleInformation(stdout_pipes[0],
310 HANDLE_FLAG_INHERIT, 0) == FALSE ||
311 SetHandleInformation(stderr_pipes[0],
312 HANDLE_FLAG_INHERIT, 0) == FALSE) {
314 pproc->last_err = GetLastError();
315 pproc->lerrno = E_SCALL;
316 return((HANDLE)pproc);
318 pproc->sv_stdin[0] = (intptr_t) stdin_pipes[0];
319 pproc->sv_stdin[1] = (intptr_t) stdin_pipes[1];
320 pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0];
321 pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1];
322 pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0];
323 pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1];
325 pproc->using_pipes = 1;
327 pproc->lerrno = 0;
329 return((HANDLE)pproc);
333 HANDLE
334 process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)
336 sub_process *pproc;
338 pproc = malloc(sizeof(*pproc));
339 memset(pproc, 0, sizeof(*pproc));
342 * Just pass the provided file handles to the 'child side' of the
343 * pipe, bypassing pipes altogether.
345 pproc->sv_stdin[1] = (intptr_t) stdinh;
346 pproc->sv_stdout[1] = (intptr_t) stdouth;
347 pproc->sv_stderr[1] = (intptr_t) stderrh;
349 pproc->last_err = pproc->lerrno = 0;
351 return((HANDLE)pproc);
355 static HANDLE
356 find_file(const char *exec_path, const char *path_var,
357 char *full_fname, DWORD full_len)
359 HANDLE exec_handle;
360 char *fname;
361 char *ext;
362 DWORD req_len;
363 int i;
364 static const char *extensions[] =
365 /* Should .com come before no-extension case? */
366 { ".exe", ".cmd", ".bat", "", ".com", NULL };
368 fname = xmalloc(strlen(exec_path) + 5);
369 strcpy(fname, exec_path);
370 ext = fname + strlen(fname);
372 for (i = 0; extensions[i]; i++) {
373 strcpy(ext, extensions[i]);
374 if (((req_len = SearchPath (path_var, fname, NULL, full_len,
375 full_fname, NULL)) > 0
376 /* For compatibility with previous code, which
377 used OpenFile, and with Windows operation in
378 general, also look in various default
379 locations, such as Windows directory and
380 Windows System directory. Warning: this also
381 searches PATH in the Make's environment, which
382 might not be what the Makefile wants, but it
383 seems to be OK as a fallback, after the
384 previous SearchPath failed to find on child's
385 PATH. */
386 || (req_len = SearchPath (NULL, fname, NULL, full_len,
387 full_fname, NULL)) > 0)
388 && req_len <= full_len
389 && (exec_handle =
390 CreateFile(full_fname,
391 GENERIC_READ,
392 FILE_SHARE_READ | FILE_SHARE_WRITE,
393 NULL,
394 OPEN_EXISTING,
395 FILE_ATTRIBUTE_NORMAL,
396 NULL)) != INVALID_HANDLE_VALUE) {
397 free(fname);
398 return(exec_handle);
402 free(fname);
403 return INVALID_HANDLE_VALUE;
408 * Description: Create the child process to be helped
410 * Returns: success <=> 0
412 * Notes/Dependencies:
414 long
415 process_begin(
416 HANDLE proc,
417 char **argv,
418 char **envp,
419 char *exec_path,
420 char *as_user)
422 sub_process *pproc = (sub_process *)proc;
423 char *shell_name = 0;
424 int file_not_found=0;
425 HANDLE exec_handle;
426 char exec_fname[MAX_PATH];
427 const char *path_var = NULL;
428 char **ep;
429 char buf[256];
430 DWORD bytes_returned;
431 DWORD flags;
432 char *command_line;
433 STARTUPINFO startInfo;
434 PROCESS_INFORMATION procInfo;
435 char *envblk=NULL;
438 * Shell script detection... if the exec_path starts with #! then
439 * we want to exec shell-script-name exec-path, not just exec-path
440 * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not
441 * hard-code the path to the shell or perl or whatever: Instead, we
442 * assume it's in the path somewhere (generally, the NT tools
443 * bin directory)
446 /* Use the Makefile's value of PATH to look for the program to
447 execute, because it could be different from Make's PATH
448 (e.g., if the target sets its own value. */
449 if (envp)
450 for (ep = envp; *ep; ep++) {
451 if (strncmp (*ep, "PATH=", 5) == 0
452 || strncmp (*ep, "Path=", 5) == 0) {
453 path_var = *ep + 5;
454 break;
457 exec_handle = find_file(exec_path, path_var,
458 exec_fname, sizeof(exec_fname));
461 * If we couldn't open the file, just assume that Windows will be
462 * somehow able to find and execute it.
464 if (exec_handle == INVALID_HANDLE_VALUE) {
465 file_not_found++;
467 else {
468 /* Attempt to read the first line of the file */
469 if (ReadFile( exec_handle,
470 buf, sizeof(buf) - 1, /* leave room for trailing NULL */
471 &bytes_returned, 0) == FALSE || bytes_returned < 2) {
473 pproc->last_err = GetLastError();
474 pproc->lerrno = E_IO;
475 CloseHandle(exec_handle);
476 return(-1);
478 if (buf[0] == '#' && buf[1] == '!') {
480 * This is a shell script... Change the command line from
481 * exec_path args to shell_name exec_path args
483 char *p;
485 /* Make sure buf is NULL terminated */
486 buf[bytes_returned] = 0;
488 * Depending on the file system type, etc. the first line
489 * of the shell script may end with newline or newline-carriage-return
490 * Whatever it ends with, cut it off.
492 p= strchr(buf, '\n');
493 if (p)
494 *p = 0;
495 p = strchr(buf, '\r');
496 if (p)
497 *p = 0;
500 * Find base name of shell
502 shell_name = strrchr( buf, '/');
503 if (shell_name) {
504 shell_name++;
505 } else {
506 shell_name = &buf[2];/* skipping "#!" */
510 CloseHandle(exec_handle);
513 flags = 0;
515 if (file_not_found)
516 command_line = make_command_line( shell_name, exec_path, argv);
517 else
518 command_line = make_command_line( shell_name, exec_fname, argv);
520 if ( command_line == NULL ) {
521 pproc->last_err = 0;
522 pproc->lerrno = E_NO_MEM;
523 return(-1);
526 if (envp) {
527 if (arr2envblk(envp, &envblk) ==FALSE) {
528 pproc->last_err = 0;
529 pproc->lerrno = E_NO_MEM;
530 free( command_line );
531 return(-1);
535 if ((shell_name) || (file_not_found)) {
536 exec_path = 0; /* Search for the program in %Path% */
537 } else {
538 exec_path = exec_fname;
542 * Set up inherited stdin, stdout, stderr for child
544 GetStartupInfo(&startInfo);
545 startInfo.dwFlags = STARTF_USESTDHANDLES;
546 startInfo.lpReserved = 0;
547 startInfo.cbReserved2 = 0;
548 startInfo.lpReserved2 = 0;
549 startInfo.lpTitle = shell_name ? shell_name : exec_path;
550 startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
551 startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
552 startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
554 if (as_user) {
555 if (envblk) free(envblk);
556 return -1;
557 } else {
558 DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n",
559 exec_path ? exec_path : "NULL",
560 command_line ? command_line : "NULL"));
561 if (CreateProcess(
562 exec_path,
563 command_line,
564 NULL,
565 0, /* default security attributes for thread */
566 TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */
567 flags,
568 envblk,
569 0, /* default starting directory */
570 &startInfo,
571 &procInfo) == FALSE) {
573 pproc->last_err = GetLastError();
574 pproc->lerrno = E_FORK;
575 fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n",
576 exec_path ? exec_path : "NULL", command_line);
577 if (envblk) free(envblk);
578 free( command_line );
579 return(-1);
583 pproc->pid = (pid_t)procInfo.hProcess;
584 /* Close the thread handle -- we'll just watch the process */
585 CloseHandle(procInfo.hThread);
587 /* Close the halves of the pipes we don't need */
588 CloseHandle((HANDLE)pproc->sv_stdin[1]);
589 CloseHandle((HANDLE)pproc->sv_stdout[1]);
590 CloseHandle((HANDLE)pproc->sv_stderr[1]);
591 pproc->sv_stdin[1] = 0;
592 pproc->sv_stdout[1] = 0;
593 pproc->sv_stderr[1] = 0;
595 free( command_line );
596 if (envblk) free(envblk);
597 pproc->lerrno=0;
598 return 0;
603 static DWORD
604 proc_stdin_thread(sub_process *pproc)
606 DWORD in_done;
607 for (;;) {
608 if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,
609 &in_done, NULL) == FALSE)
610 _endthreadex(0);
611 // This if should never be true for anonymous pipes, but gives
612 // us a chance to change I/O mechanisms later
613 if (in_done < pproc->incnt) {
614 pproc->incnt -= in_done;
615 pproc->inp += in_done;
616 } else {
617 _endthreadex(0);
620 return 0; // for compiler warnings only.. not reached
623 static DWORD
624 proc_stdout_thread(sub_process *pproc)
626 DWORD bufsize = 1024;
627 char c;
628 DWORD nread;
629 pproc->outp = malloc(bufsize);
630 if (pproc->outp == NULL)
631 _endthreadex(0);
632 pproc->outcnt = 0;
634 for (;;) {
635 if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL)
636 == FALSE) {
637 /* map_windows32_error_to_string(GetLastError());*/
638 _endthreadex(0);
640 if (nread == 0)
641 _endthreadex(0);
642 if (pproc->outcnt + nread > bufsize) {
643 bufsize += nread + 512;
644 pproc->outp = realloc(pproc->outp, bufsize);
645 if (pproc->outp == NULL) {
646 pproc->outcnt = 0;
647 _endthreadex(0);
650 pproc->outp[pproc->outcnt++] = c;
652 return 0;
655 static DWORD
656 proc_stderr_thread(sub_process *pproc)
658 DWORD bufsize = 1024;
659 char c;
660 DWORD nread;
661 pproc->errp = malloc(bufsize);
662 if (pproc->errp == NULL)
663 _endthreadex(0);
664 pproc->errcnt = 0;
666 for (;;) {
667 if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {
668 map_windows32_error_to_string(GetLastError());
669 _endthreadex(0);
671 if (nread == 0)
672 _endthreadex(0);
673 if (pproc->errcnt + nread > bufsize) {
674 bufsize += nread + 512;
675 pproc->errp = realloc(pproc->errp, bufsize);
676 if (pproc->errp == NULL) {
677 pproc->errcnt = 0;
678 _endthreadex(0);
681 pproc->errp[pproc->errcnt++] = c;
683 return 0;
688 * Purpose: collects output from child process and returns results
690 * Description:
692 * Returns:
694 * Notes/Dependencies:
696 long
697 process_pipe_io(
698 HANDLE proc,
699 char *stdin_data,
700 int stdin_data_len)
702 sub_process *pproc = (sub_process *)proc;
703 bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;
704 HANDLE childhand = (HANDLE) pproc->pid;
705 HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL;
706 unsigned int dwStdin, dwStdout, dwStderr;
707 HANDLE wait_list[4];
708 DWORD wait_count;
709 DWORD wait_return;
710 HANDLE ready_hand;
711 bool_t child_dead = FALSE;
712 BOOL GetExitCodeResult;
715 * Create stdin thread, if needed
717 pproc->inp = stdin_data;
718 pproc->incnt = stdin_data_len;
719 if (!pproc->inp) {
720 stdin_eof = TRUE;
721 CloseHandle((HANDLE)pproc->sv_stdin[0]);
722 pproc->sv_stdin[0] = 0;
723 } else {
724 tStdin = (HANDLE) _beginthreadex( 0, 1024,
725 (unsigned (__stdcall *) (void *))proc_stdin_thread,
726 pproc, 0, &dwStdin);
727 if (tStdin == 0) {
728 pproc->last_err = GetLastError();
729 pproc->lerrno = E_SCALL;
730 goto done;
735 * Assume child will produce stdout and stderr
737 tStdout = (HANDLE) _beginthreadex( 0, 1024,
738 (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,
739 &dwStdout);
740 tStderr = (HANDLE) _beginthreadex( 0, 1024,
741 (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,
742 &dwStderr);
744 if (tStdout == 0 || tStderr == 0) {
746 pproc->last_err = GetLastError();
747 pproc->lerrno = E_SCALL;
748 goto done;
753 * Wait for all I/O to finish and for the child process to exit
756 while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
757 wait_count = 0;
758 if (!stdin_eof) {
759 wait_list[wait_count++] = tStdin;
761 if (!stdout_eof) {
762 wait_list[wait_count++] = tStdout;
764 if (!stderr_eof) {
765 wait_list[wait_count++] = tStderr;
767 if (!child_dead) {
768 wait_list[wait_count++] = childhand;
771 wait_return = WaitForMultipleObjects(wait_count, wait_list,
772 FALSE, /* don't wait for all: one ready will do */
773 child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
774 one second to collect all remaining output */
776 if (wait_return == WAIT_FAILED) {
777 /* map_windows32_error_to_string(GetLastError());*/
778 pproc->last_err = GetLastError();
779 pproc->lerrno = E_SCALL;
780 goto done;
783 ready_hand = wait_list[wait_return - WAIT_OBJECT_0];
785 if (ready_hand == tStdin) {
786 CloseHandle((HANDLE)pproc->sv_stdin[0]);
787 pproc->sv_stdin[0] = 0;
788 CloseHandle(tStdin);
789 tStdin = 0;
790 stdin_eof = TRUE;
792 } else if (ready_hand == tStdout) {
794 CloseHandle((HANDLE)pproc->sv_stdout[0]);
795 pproc->sv_stdout[0] = 0;
796 CloseHandle(tStdout);
797 tStdout = 0;
798 stdout_eof = TRUE;
800 } else if (ready_hand == tStderr) {
802 CloseHandle((HANDLE)pproc->sv_stderr[0]);
803 pproc->sv_stderr[0] = 0;
804 CloseHandle(tStderr);
805 tStderr = 0;
806 stderr_eof = TRUE;
808 } else if (ready_hand == childhand) {
810 DWORD ierr;
811 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
812 if (ierr == CONTROL_C_EXIT) {
813 pproc->signal = SIGINT;
814 } else {
815 pproc->exit_code = ierr;
817 if (GetExitCodeResult == FALSE) {
818 pproc->last_err = GetLastError();
819 pproc->lerrno = E_SCALL;
820 goto done;
822 child_dead = TRUE;
824 } else {
826 /* ?? Got back a handle we didn't query ?? */
827 pproc->last_err = 0;
828 pproc->lerrno = E_FAIL;
829 goto done;
833 done:
834 if (tStdin != 0)
835 CloseHandle(tStdin);
836 if (tStdout != 0)
837 CloseHandle(tStdout);
838 if (tStderr != 0)
839 CloseHandle(tStderr);
841 if (pproc->lerrno)
842 return(-1);
843 else
844 return(0);
849 * Purpose: collects output from child process and returns results
851 * Description:
853 * Returns:
855 * Notes/Dependencies:
857 long
858 process_file_io(
859 HANDLE proc)
861 sub_process *pproc;
862 HANDLE childhand;
863 DWORD wait_return;
864 BOOL GetExitCodeResult;
865 DWORD ierr;
867 if (proc == NULL)
868 pproc = process_wait_for_any_private();
869 else
870 pproc = (sub_process *)proc;
872 /* some sort of internal error */
873 if (!pproc)
874 return -1;
876 childhand = (HANDLE) pproc->pid;
879 * This function is poorly named, and could also be used just to wait
880 * for child death if you're doing your own pipe I/O. If that is
881 * the case, close the pipe handles here.
883 if (pproc->sv_stdin[0]) {
884 CloseHandle((HANDLE)pproc->sv_stdin[0]);
885 pproc->sv_stdin[0] = 0;
887 if (pproc->sv_stdout[0]) {
888 CloseHandle((HANDLE)pproc->sv_stdout[0]);
889 pproc->sv_stdout[0] = 0;
891 if (pproc->sv_stderr[0]) {
892 CloseHandle((HANDLE)pproc->sv_stderr[0]);
893 pproc->sv_stderr[0] = 0;
897 * Wait for the child process to exit
900 wait_return = WaitForSingleObject(childhand, INFINITE);
902 if (wait_return != WAIT_OBJECT_0) {
903 /* map_windows32_error_to_string(GetLastError());*/
904 pproc->last_err = GetLastError();
905 pproc->lerrno = E_SCALL;
906 goto done2;
909 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
910 if (ierr == CONTROL_C_EXIT) {
911 pproc->signal = SIGINT;
912 } else {
913 pproc->exit_code = ierr;
915 if (GetExitCodeResult == FALSE) {
916 pproc->last_err = GetLastError();
917 pproc->lerrno = E_SCALL;
920 done2:
921 if (pproc->lerrno)
922 return(-1);
923 else
924 return(0);
929 * Description: Clean up any leftover handles, etc. It is up to the
930 * caller to manage and free the input, ouput, and stderr buffers.
932 void
933 process_cleanup(
934 HANDLE proc)
936 sub_process *pproc = (sub_process *)proc;
937 int i;
939 if (pproc->using_pipes) {
940 for (i= 0; i <= 1; i++) {
941 if ((HANDLE)pproc->sv_stdin[i])
942 CloseHandle((HANDLE)pproc->sv_stdin[i]);
943 if ((HANDLE)pproc->sv_stdout[i])
944 CloseHandle((HANDLE)pproc->sv_stdout[i]);
945 if ((HANDLE)pproc->sv_stderr[i])
946 CloseHandle((HANDLE)pproc->sv_stderr[i]);
949 if ((HANDLE)pproc->pid)
950 CloseHandle((HANDLE)pproc->pid);
952 free(pproc);
957 * Description:
958 * Create a command line buffer to pass to CreateProcess
960 * Returns: the buffer or NULL for failure
961 * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ...
962 * Otherwise: argv[0] argv[1] argv[2] ...
964 * Notes/Dependencies:
965 * CreateProcess does not take an argv, so this command creates a
966 * command line for the executable.
969 static char *
970 make_command_line( char *shell_name, char *full_exec_path, char **argv)
972 int argc = 0;
973 char** argvi;
974 int* enclose_in_quotes = NULL;
975 int* enclose_in_quotes_i;
976 unsigned int bytes_required = 0;
977 char* command_line;
978 char* command_line_i;
979 int cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */
980 int have_sh = 0; /* HAVE_CYGWIN_SHELL */
982 #ifdef HAVE_CYGWIN_SHELL
983 have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe"));
984 cygwin_mode = 1;
985 #endif
987 if (shell_name && full_exec_path) {
988 bytes_required
989 = strlen(shell_name) + 1 + strlen(full_exec_path);
991 * Skip argv[0] if any, when shell_name is given.
993 if (*argv) argv++;
995 * Add one for the intervening space.
997 if (*argv) bytes_required++;
1000 argvi = argv;
1001 while (*(argvi++)) argc++;
1003 if (argc) {
1004 enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));
1006 if (!enclose_in_quotes) {
1007 return NULL;
1011 /* We have to make one pass through each argv[i] to see if we need
1012 * to enclose it in ", so we might as well figure out how much
1013 * memory we'll need on the same pass.
1016 argvi = argv;
1017 enclose_in_quotes_i = enclose_in_quotes;
1018 while(*argvi) {
1019 char* p = *argvi;
1020 unsigned int backslash_count = 0;
1023 * We have to enclose empty arguments in ".
1025 if (!(*p)) *enclose_in_quotes_i = 1;
1027 while(*p) {
1028 switch (*p) {
1029 case '\"':
1031 * We have to insert a backslash for each "
1032 * and each \ that precedes the ".
1034 bytes_required += (backslash_count + 1);
1035 backslash_count = 0;
1036 break;
1038 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1039 case '\\':
1040 backslash_count++;
1041 break;
1042 #endif
1044 * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
1045 * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
1046 * that argv in always equals argv out. This was removed. Say you have
1047 * such a program named glob.exe. You enter
1048 * glob '*'
1049 * at the sh command prompt. Obviously the intent is to make glob do the
1050 * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?',
1051 * then the command line that glob would see would be
1052 * glob "*"
1053 * and the _setargv in SETARGV.OBJ would _not_ expand the *.
1055 case ' ':
1056 case '\t':
1057 *enclose_in_quotes_i = 1;
1058 /* fall through */
1060 default:
1061 backslash_count = 0;
1062 break;
1066 * Add one for each character in argv[i].
1068 bytes_required++;
1070 p++;
1073 if (*enclose_in_quotes_i) {
1075 * Add one for each enclosing ",
1076 * and one for each \ that precedes the
1077 * closing ".
1079 bytes_required += (backslash_count + 2);
1083 * Add one for the intervening space.
1085 if (*(++argvi)) bytes_required++;
1086 enclose_in_quotes_i++;
1090 * Add one for the terminating NULL.
1092 bytes_required++;
1094 command_line = (char*) malloc(bytes_required);
1096 if (!command_line) {
1097 if (enclose_in_quotes) free(enclose_in_quotes);
1098 return NULL;
1101 command_line_i = command_line;
1103 if (shell_name && full_exec_path) {
1104 while(*shell_name) {
1105 *(command_line_i++) = *(shell_name++);
1108 *(command_line_i++) = ' ';
1110 while(*full_exec_path) {
1111 *(command_line_i++) = *(full_exec_path++);
1114 if (*argv) {
1115 *(command_line_i++) = ' ';
1119 argvi = argv;
1120 enclose_in_quotes_i = enclose_in_quotes;
1122 while(*argvi) {
1123 char* p = *argvi;
1124 unsigned int backslash_count = 0;
1126 if (*enclose_in_quotes_i) {
1127 *(command_line_i++) = '\"';
1130 while(*p) {
1131 if (*p == '\"') {
1132 if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */
1133 /* instead of a \", cygwin likes "" */
1134 *(command_line_i++) = '\"';
1135 } else {
1138 * We have to insert a backslash for the "
1139 * and each \ that precedes the ".
1141 backslash_count++;
1143 while(backslash_count) {
1144 *(command_line_i++) = '\\';
1145 backslash_count--;
1148 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1149 } else if (*p == '\\') {
1150 backslash_count++;
1151 } else {
1152 backslash_count = 0;
1153 #endif
1157 * Copy the character.
1159 *(command_line_i++) = *(p++);
1162 if (*enclose_in_quotes_i) {
1163 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1165 * Add one \ for each \ that precedes the
1166 * closing ".
1168 while(backslash_count--) {
1169 *(command_line_i++) = '\\';
1171 #endif
1172 *(command_line_i++) = '\"';
1176 * Append an intervening space.
1178 if (*(++argvi)) {
1179 *(command_line_i++) = ' ';
1182 enclose_in_quotes_i++;
1186 * Append the terminating NULL.
1188 *command_line_i = '\0';
1190 if (enclose_in_quotes) free(enclose_in_quotes);
1191 return command_line;
1195 * Description: Given an argv and optional envp, launch the process
1196 * using the default stdin, stdout, and stderr handles.
1197 * Also, register process so that process_wait_for_any_private()
1198 * can be used via process_file_io(NULL) or
1199 * process_wait_for_any().
1201 * Returns:
1203 * Notes/Dependencies:
1205 HANDLE
1206 process_easy(
1207 char **argv,
1208 char **envp)
1210 HANDLE hIn;
1211 HANDLE hOut;
1212 HANDLE hErr;
1213 HANDLE hProcess;
1215 if (proc_index >= MAXIMUM_WAIT_OBJECTS) {
1216 DB (DB_JOBS, ("process_easy: All process slots used up\n"));
1217 return INVALID_HANDLE_VALUE;
1219 if (DuplicateHandle(GetCurrentProcess(),
1220 GetStdHandle(STD_INPUT_HANDLE),
1221 GetCurrentProcess(),
1222 &hIn,
1224 TRUE,
1225 DUPLICATE_SAME_ACCESS) == FALSE) {
1226 fprintf(stderr,
1227 "process_easy: DuplicateHandle(In) failed (e=%ld)\n",
1228 GetLastError());
1229 return INVALID_HANDLE_VALUE;
1231 if (DuplicateHandle(GetCurrentProcess(),
1232 GetStdHandle(STD_OUTPUT_HANDLE),
1233 GetCurrentProcess(),
1234 &hOut,
1236 TRUE,
1237 DUPLICATE_SAME_ACCESS) == FALSE) {
1238 fprintf(stderr,
1239 "process_easy: DuplicateHandle(Out) failed (e=%ld)\n",
1240 GetLastError());
1241 return INVALID_HANDLE_VALUE;
1243 if (DuplicateHandle(GetCurrentProcess(),
1244 GetStdHandle(STD_ERROR_HANDLE),
1245 GetCurrentProcess(),
1246 &hErr,
1248 TRUE,
1249 DUPLICATE_SAME_ACCESS) == FALSE) {
1250 fprintf(stderr,
1251 "process_easy: DuplicateHandle(Err) failed (e=%ld)\n",
1252 GetLastError());
1253 return INVALID_HANDLE_VALUE;
1256 hProcess = process_init_fd(hIn, hOut, hErr);
1258 if (process_begin(hProcess, argv, envp, argv[0], NULL)) {
1259 fake_exits_pending++;
1260 /* process_begin() failed: make a note of that. */
1261 if (!((sub_process*) hProcess)->last_err)
1262 ((sub_process*) hProcess)->last_err = -1;
1263 ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);
1265 /* close up unused handles */
1266 CloseHandle(hIn);
1267 CloseHandle(hOut);
1268 CloseHandle(hErr);
1271 process_register(hProcess);
1273 return hProcess;