Update copyrights for 2010.
[make.git] / w32 / subproc / sub_proc.c
blobf0597b001588147442c71825f10e9c141af9fe8d
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 <stdlib.h>
19 #include <stdio.h>
20 #include <stdint.h>
21 #include <process.h> /* for msvc _beginthreadex, _endthreadex */
22 #include <signal.h>
23 #include <windows.h>
25 #include "sub_proc.h"
26 #include "proc.h"
27 #include "w32err.h"
28 #include "config.h"
29 #include "debug.h"
31 static char *make_command_line(char *shell_name, char *exec_path, char **argv);
32 extern char *xmalloc (unsigned int);
34 typedef struct sub_process_t {
35 intptr_t sv_stdin[2];
36 intptr_t sv_stdout[2];
37 intptr_t sv_stderr[2];
38 int using_pipes;
39 char *inp;
40 DWORD incnt;
41 char * volatile outp;
42 volatile DWORD outcnt;
43 char * volatile errp;
44 volatile DWORD errcnt;
45 pid_t pid;
46 int exit_code;
47 int signal;
48 long last_err;
49 long lerrno;
50 } sub_process;
52 /* keep track of children so we can implement a waitpid-like routine */
53 static sub_process *proc_array[MAXIMUM_WAIT_OBJECTS];
54 static int proc_index = 0;
55 static int fake_exits_pending = 0;
58 * When a process has been waited for, adjust the wait state
59 * array so that we don't wait for it again
61 static void
62 process_adjust_wait_state(sub_process* pproc)
64 int i;
66 if (!proc_index)
67 return;
69 for (i = 0; i < proc_index; i++)
70 if (proc_array[i]->pid == pproc->pid)
71 break;
73 if (i < proc_index) {
74 proc_index--;
75 if (i != proc_index)
76 memmove(&proc_array[i], &proc_array[i+1],
77 (proc_index-i) * sizeof(sub_process*));
78 proc_array[proc_index] = NULL;
83 * Waits for any of the registered child processes to finish.
85 static sub_process *
86 process_wait_for_any_private(void)
88 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
89 DWORD retval, which;
90 int i;
92 if (!proc_index)
93 return NULL;
95 /* build array of handles to wait for */
96 for (i = 0; i < proc_index; i++) {
97 handles[i] = (HANDLE) proc_array[i]->pid;
99 if (fake_exits_pending && proc_array[i]->exit_code)
100 break;
103 /* wait for someone to exit */
104 if (!fake_exits_pending) {
105 retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE);
106 which = retval - WAIT_OBJECT_0;
107 } else {
108 fake_exits_pending--;
109 retval = !WAIT_FAILED;
110 which = i;
113 /* return pointer to process */
114 if (retval != WAIT_FAILED) {
115 sub_process* pproc = proc_array[which];
116 process_adjust_wait_state(pproc);
117 return pproc;
118 } else
119 return NULL;
123 * Terminate a process.
125 BOOL
126 process_kill(HANDLE proc, int signal)
128 sub_process* pproc = (sub_process*) proc;
129 pproc->signal = signal;
130 return (TerminateProcess((HANDLE) pproc->pid, signal));
134 * Use this function to register processes you wish to wait for by
135 * calling process_file_io(NULL) or process_wait_any(). This must be done
136 * because it is possible for callers of this library to reuse the same
137 * handle for multiple processes launches :-(
139 void
140 process_register(HANDLE proc)
142 if (proc_index < MAXIMUM_WAIT_OBJECTS)
143 proc_array[proc_index++] = (sub_process *) proc;
147 * Return the number of processes that we are still waiting for.
150 process_used_slots(void)
152 return proc_index;
156 * Public function which works kind of like waitpid(). Wait for any
157 * of the children to die and return results. To call this function,
158 * you must do 1 of things:
160 * x = process_easy(...);
162 * or
164 * x = process_init_fd();
165 * process_register(x);
167 * or
169 * x = process_init();
170 * process_register(x);
172 * You must NOT then call process_pipe_io() because this function is
173 * not capable of handling automatic notification of any child
174 * death.
177 HANDLE
178 process_wait_for_any(void)
180 sub_process* pproc = process_wait_for_any_private();
182 if (!pproc)
183 return NULL;
184 else {
186 * Ouch! can't tell caller if this fails directly. Caller
187 * will have to use process_last_err()
189 (void) process_file_io(pproc);
190 return ((HANDLE) pproc);
194 long
195 process_signal(HANDLE proc)
197 if (proc == INVALID_HANDLE_VALUE) return 0;
198 return (((sub_process *)proc)->signal);
201 long
202 process_last_err(HANDLE proc)
204 if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
205 return (((sub_process *)proc)->last_err);
208 long
209 process_exit_code(HANDLE proc)
211 if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE;
212 return (((sub_process *)proc)->exit_code);
216 2006-02:
217 All the following functions are currently unused.
218 All of them would crash gmake if called with argument INVALID_HANDLE_VALUE.
219 Hence whoever wants to use one of this functions must invent and implement
220 a reasonable error handling for this function.
222 char *
223 process_outbuf(HANDLE proc)
225 return (((sub_process *)proc)->outp);
228 char *
229 process_errbuf(HANDLE proc)
231 return (((sub_process *)proc)->errp);
235 process_outcnt(HANDLE proc)
237 return (((sub_process *)proc)->outcnt);
241 process_errcnt(HANDLE proc)
243 return (((sub_process *)proc)->errcnt);
246 void
247 process_pipes(HANDLE proc, int pipes[3])
249 pipes[0] = ((sub_process *)proc)->sv_stdin[0];
250 pipes[1] = ((sub_process *)proc)->sv_stdout[0];
251 pipes[2] = ((sub_process *)proc)->sv_stderr[0];
252 return;
256 HANDLE
257 process_init()
259 sub_process *pproc;
261 * open file descriptors for attaching stdin/stdout/sterr
263 HANDLE stdin_pipes[2];
264 HANDLE stdout_pipes[2];
265 HANDLE stderr_pipes[2];
266 SECURITY_ATTRIBUTES inherit;
267 BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
269 pproc = malloc(sizeof(*pproc));
270 memset(pproc, 0, sizeof(*pproc));
272 /* We can't use NULL for lpSecurityDescriptor because that
273 uses the default security descriptor of the calling process.
274 Instead we use a security descriptor with no DACL. This
275 allows nonrestricted access to the associated objects. */
277 if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),
278 SECURITY_DESCRIPTOR_REVISION)) {
279 pproc->last_err = GetLastError();
280 pproc->lerrno = E_SCALL;
281 return((HANDLE)pproc);
284 inherit.nLength = sizeof(inherit);
285 inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);
286 inherit.bInheritHandle = TRUE;
288 // By convention, parent gets pipe[0], and child gets pipe[1]
289 // This means the READ side of stdin pipe goes into pipe[1]
290 // and the WRITE side of the stdout and stderr pipes go into pipe[1]
291 if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||
292 CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||
293 CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {
295 pproc->last_err = GetLastError();
296 pproc->lerrno = E_SCALL;
297 return((HANDLE)pproc);
301 // Mark the parent sides of the pipes as non-inheritable
303 if (SetHandleInformation(stdin_pipes[0],
304 HANDLE_FLAG_INHERIT, 0) == FALSE ||
305 SetHandleInformation(stdout_pipes[0],
306 HANDLE_FLAG_INHERIT, 0) == FALSE ||
307 SetHandleInformation(stderr_pipes[0],
308 HANDLE_FLAG_INHERIT, 0) == FALSE) {
310 pproc->last_err = GetLastError();
311 pproc->lerrno = E_SCALL;
312 return((HANDLE)pproc);
314 pproc->sv_stdin[0] = (intptr_t) stdin_pipes[0];
315 pproc->sv_stdin[1] = (intptr_t) stdin_pipes[1];
316 pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0];
317 pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1];
318 pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0];
319 pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1];
321 pproc->using_pipes = 1;
323 pproc->lerrno = 0;
325 return((HANDLE)pproc);
329 HANDLE
330 process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)
332 sub_process *pproc;
334 pproc = malloc(sizeof(*pproc));
335 memset(pproc, 0, sizeof(*pproc));
338 * Just pass the provided file handles to the 'child side' of the
339 * pipe, bypassing pipes altogether.
341 pproc->sv_stdin[1] = (intptr_t) stdinh;
342 pproc->sv_stdout[1] = (intptr_t) stdouth;
343 pproc->sv_stderr[1] = (intptr_t) stderrh;
345 pproc->last_err = pproc->lerrno = 0;
347 return((HANDLE)pproc);
351 static HANDLE
352 find_file(const char *exec_path, const char *path_var,
353 char *full_fname, DWORD full_len)
355 HANDLE exec_handle;
356 char *fname;
357 char *ext;
358 DWORD req_len;
359 int i;
360 static const char *extensions[] =
361 /* Should .com come before no-extension case? */
362 { ".exe", ".cmd", ".bat", "", ".com", NULL };
364 fname = xmalloc(strlen(exec_path) + 5);
365 strcpy(fname, exec_path);
366 ext = fname + strlen(fname);
368 for (i = 0; extensions[i]; i++) {
369 strcpy(ext, extensions[i]);
370 if (((req_len = SearchPath (path_var, fname, NULL, full_len,
371 full_fname, NULL)) > 0
372 /* For compatibility with previous code, which
373 used OpenFile, and with Windows operation in
374 general, also look in various default
375 locations, such as Windows directory and
376 Windows System directory. Warning: this also
377 searches PATH in the Make's environment, which
378 might not be what the Makefile wants, but it
379 seems to be OK as a fallback, after the
380 previous SearchPath failed to find on child's
381 PATH. */
382 || (req_len = SearchPath (NULL, fname, NULL, full_len,
383 full_fname, NULL)) > 0)
384 && req_len <= full_len
385 && (exec_handle =
386 CreateFile(full_fname,
387 GENERIC_READ,
388 FILE_SHARE_READ | FILE_SHARE_WRITE,
389 NULL,
390 OPEN_EXISTING,
391 FILE_ATTRIBUTE_NORMAL,
392 NULL)) != INVALID_HANDLE_VALUE) {
393 free(fname);
394 return(exec_handle);
398 free(fname);
399 return INVALID_HANDLE_VALUE;
404 * Description: Create the child process to be helped
406 * Returns: success <=> 0
408 * Notes/Dependencies:
410 long
411 process_begin(
412 HANDLE proc,
413 char **argv,
414 char **envp,
415 char *exec_path,
416 char *as_user)
418 sub_process *pproc = (sub_process *)proc;
419 char *shell_name = 0;
420 int file_not_found=0;
421 HANDLE exec_handle;
422 char exec_fname[MAX_PATH];
423 const char *path_var = NULL;
424 char **ep;
425 char buf[256];
426 DWORD bytes_returned;
427 DWORD flags;
428 char *command_line;
429 STARTUPINFO startInfo;
430 PROCESS_INFORMATION procInfo;
431 char *envblk=NULL;
434 * Shell script detection... if the exec_path starts with #! then
435 * we want to exec shell-script-name exec-path, not just exec-path
436 * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not
437 * hard-code the path to the shell or perl or whatever: Instead, we
438 * assume it's in the path somewhere (generally, the NT tools
439 * bin directory)
442 /* Use the Makefile's value of PATH to look for the program to
443 execute, because it could be different from Make's PATH
444 (e.g., if the target sets its own value. */
445 if (envp)
446 for (ep = envp; *ep; ep++) {
447 if (strncmp (*ep, "PATH=", 5) == 0
448 || strncmp (*ep, "Path=", 5) == 0) {
449 path_var = *ep + 5;
450 break;
453 exec_handle = find_file(exec_path, path_var,
454 exec_fname, sizeof(exec_fname));
457 * If we couldn't open the file, just assume that Windows will be
458 * somehow able to find and execute it.
460 if (exec_handle == INVALID_HANDLE_VALUE) {
461 file_not_found++;
463 else {
464 /* Attempt to read the first line of the file */
465 if (ReadFile( exec_handle,
466 buf, sizeof(buf) - 1, /* leave room for trailing NULL */
467 &bytes_returned, 0) == FALSE || bytes_returned < 2) {
469 pproc->last_err = GetLastError();
470 pproc->lerrno = E_IO;
471 CloseHandle(exec_handle);
472 return(-1);
474 if (buf[0] == '#' && buf[1] == '!') {
476 * This is a shell script... Change the command line from
477 * exec_path args to shell_name exec_path args
479 char *p;
481 /* Make sure buf is NULL terminated */
482 buf[bytes_returned] = 0;
484 * Depending on the file system type, etc. the first line
485 * of the shell script may end with newline or newline-carriage-return
486 * Whatever it ends with, cut it off.
488 p= strchr(buf, '\n');
489 if (p)
490 *p = 0;
491 p = strchr(buf, '\r');
492 if (p)
493 *p = 0;
496 * Find base name of shell
498 shell_name = strrchr( buf, '/');
499 if (shell_name) {
500 shell_name++;
501 } else {
502 shell_name = &buf[2];/* skipping "#!" */
506 CloseHandle(exec_handle);
509 flags = 0;
511 if (file_not_found)
512 command_line = make_command_line( shell_name, exec_path, argv);
513 else
514 command_line = make_command_line( shell_name, exec_fname, argv);
516 if ( command_line == NULL ) {
517 pproc->last_err = 0;
518 pproc->lerrno = E_NO_MEM;
519 return(-1);
522 if (envp) {
523 if (arr2envblk(envp, &envblk) ==FALSE) {
524 pproc->last_err = 0;
525 pproc->lerrno = E_NO_MEM;
526 free( command_line );
527 return(-1);
531 if ((shell_name) || (file_not_found)) {
532 exec_path = 0; /* Search for the program in %Path% */
533 } else {
534 exec_path = exec_fname;
538 * Set up inherited stdin, stdout, stderr for child
540 GetStartupInfo(&startInfo);
541 startInfo.dwFlags = STARTF_USESTDHANDLES;
542 startInfo.lpReserved = 0;
543 startInfo.cbReserved2 = 0;
544 startInfo.lpReserved2 = 0;
545 startInfo.lpTitle = shell_name ? shell_name : exec_path;
546 startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
547 startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
548 startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
550 if (as_user) {
551 if (envblk) free(envblk);
552 return -1;
553 } else {
554 DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n",
555 exec_path ? exec_path : "NULL",
556 command_line ? command_line : "NULL"));
557 if (CreateProcess(
558 exec_path,
559 command_line,
560 NULL,
561 0, /* default security attributes for thread */
562 TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */
563 flags,
564 envblk,
565 0, /* default starting directory */
566 &startInfo,
567 &procInfo) == FALSE) {
569 pproc->last_err = GetLastError();
570 pproc->lerrno = E_FORK;
571 fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n",
572 exec_path ? exec_path : "NULL", command_line);
573 if (envblk) free(envblk);
574 free( command_line );
575 return(-1);
579 pproc->pid = (pid_t)procInfo.hProcess;
580 /* Close the thread handle -- we'll just watch the process */
581 CloseHandle(procInfo.hThread);
583 /* Close the halves of the pipes we don't need */
584 CloseHandle((HANDLE)pproc->sv_stdin[1]);
585 CloseHandle((HANDLE)pproc->sv_stdout[1]);
586 CloseHandle((HANDLE)pproc->sv_stderr[1]);
587 pproc->sv_stdin[1] = 0;
588 pproc->sv_stdout[1] = 0;
589 pproc->sv_stderr[1] = 0;
591 free( command_line );
592 if (envblk) free(envblk);
593 pproc->lerrno=0;
594 return 0;
599 static DWORD
600 proc_stdin_thread(sub_process *pproc)
602 DWORD in_done;
603 for (;;) {
604 if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,
605 &in_done, NULL) == FALSE)
606 _endthreadex(0);
607 // This if should never be true for anonymous pipes, but gives
608 // us a chance to change I/O mechanisms later
609 if (in_done < pproc->incnt) {
610 pproc->incnt -= in_done;
611 pproc->inp += in_done;
612 } else {
613 _endthreadex(0);
616 return 0; // for compiler warnings only.. not reached
619 static DWORD
620 proc_stdout_thread(sub_process *pproc)
622 DWORD bufsize = 1024;
623 char c;
624 DWORD nread;
625 pproc->outp = malloc(bufsize);
626 if (pproc->outp == NULL)
627 _endthreadex(0);
628 pproc->outcnt = 0;
630 for (;;) {
631 if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL)
632 == FALSE) {
633 /* map_windows32_error_to_string(GetLastError());*/
634 _endthreadex(0);
636 if (nread == 0)
637 _endthreadex(0);
638 if (pproc->outcnt + nread > bufsize) {
639 bufsize += nread + 512;
640 pproc->outp = realloc(pproc->outp, bufsize);
641 if (pproc->outp == NULL) {
642 pproc->outcnt = 0;
643 _endthreadex(0);
646 pproc->outp[pproc->outcnt++] = c;
648 return 0;
651 static DWORD
652 proc_stderr_thread(sub_process *pproc)
654 DWORD bufsize = 1024;
655 char c;
656 DWORD nread;
657 pproc->errp = malloc(bufsize);
658 if (pproc->errp == NULL)
659 _endthreadex(0);
660 pproc->errcnt = 0;
662 for (;;) {
663 if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {
664 map_windows32_error_to_string(GetLastError());
665 _endthreadex(0);
667 if (nread == 0)
668 _endthreadex(0);
669 if (pproc->errcnt + nread > bufsize) {
670 bufsize += nread + 512;
671 pproc->errp = realloc(pproc->errp, bufsize);
672 if (pproc->errp == NULL) {
673 pproc->errcnt = 0;
674 _endthreadex(0);
677 pproc->errp[pproc->errcnt++] = c;
679 return 0;
684 * Purpose: collects output from child process and returns results
686 * Description:
688 * Returns:
690 * Notes/Dependencies:
692 long
693 process_pipe_io(
694 HANDLE proc,
695 char *stdin_data,
696 int stdin_data_len)
698 sub_process *pproc = (sub_process *)proc;
699 bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;
700 HANDLE childhand = (HANDLE) pproc->pid;
701 HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL;
702 unsigned int dwStdin, dwStdout, dwStderr;
703 HANDLE wait_list[4];
704 DWORD wait_count;
705 DWORD wait_return;
706 HANDLE ready_hand;
707 bool_t child_dead = FALSE;
708 BOOL GetExitCodeResult;
711 * Create stdin thread, if needed
713 pproc->inp = stdin_data;
714 pproc->incnt = stdin_data_len;
715 if (!pproc->inp) {
716 stdin_eof = TRUE;
717 CloseHandle((HANDLE)pproc->sv_stdin[0]);
718 pproc->sv_stdin[0] = 0;
719 } else {
720 tStdin = (HANDLE) _beginthreadex( 0, 1024,
721 (unsigned (__stdcall *) (void *))proc_stdin_thread,
722 pproc, 0, &dwStdin);
723 if (tStdin == 0) {
724 pproc->last_err = GetLastError();
725 pproc->lerrno = E_SCALL;
726 goto done;
731 * Assume child will produce stdout and stderr
733 tStdout = (HANDLE) _beginthreadex( 0, 1024,
734 (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,
735 &dwStdout);
736 tStderr = (HANDLE) _beginthreadex( 0, 1024,
737 (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,
738 &dwStderr);
740 if (tStdout == 0 || tStderr == 0) {
742 pproc->last_err = GetLastError();
743 pproc->lerrno = E_SCALL;
744 goto done;
749 * Wait for all I/O to finish and for the child process to exit
752 while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
753 wait_count = 0;
754 if (!stdin_eof) {
755 wait_list[wait_count++] = tStdin;
757 if (!stdout_eof) {
758 wait_list[wait_count++] = tStdout;
760 if (!stderr_eof) {
761 wait_list[wait_count++] = tStderr;
763 if (!child_dead) {
764 wait_list[wait_count++] = childhand;
767 wait_return = WaitForMultipleObjects(wait_count, wait_list,
768 FALSE, /* don't wait for all: one ready will do */
769 child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
770 one second to collect all remaining output */
772 if (wait_return == WAIT_FAILED) {
773 /* map_windows32_error_to_string(GetLastError());*/
774 pproc->last_err = GetLastError();
775 pproc->lerrno = E_SCALL;
776 goto done;
779 ready_hand = wait_list[wait_return - WAIT_OBJECT_0];
781 if (ready_hand == tStdin) {
782 CloseHandle((HANDLE)pproc->sv_stdin[0]);
783 pproc->sv_stdin[0] = 0;
784 CloseHandle(tStdin);
785 tStdin = 0;
786 stdin_eof = TRUE;
788 } else if (ready_hand == tStdout) {
790 CloseHandle((HANDLE)pproc->sv_stdout[0]);
791 pproc->sv_stdout[0] = 0;
792 CloseHandle(tStdout);
793 tStdout = 0;
794 stdout_eof = TRUE;
796 } else if (ready_hand == tStderr) {
798 CloseHandle((HANDLE)pproc->sv_stderr[0]);
799 pproc->sv_stderr[0] = 0;
800 CloseHandle(tStderr);
801 tStderr = 0;
802 stderr_eof = TRUE;
804 } else if (ready_hand == childhand) {
806 DWORD ierr;
807 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
808 if (ierr == CONTROL_C_EXIT) {
809 pproc->signal = SIGINT;
810 } else {
811 pproc->exit_code = ierr;
813 if (GetExitCodeResult == FALSE) {
814 pproc->last_err = GetLastError();
815 pproc->lerrno = E_SCALL;
816 goto done;
818 child_dead = TRUE;
820 } else {
822 /* ?? Got back a handle we didn't query ?? */
823 pproc->last_err = 0;
824 pproc->lerrno = E_FAIL;
825 goto done;
829 done:
830 if (tStdin != 0)
831 CloseHandle(tStdin);
832 if (tStdout != 0)
833 CloseHandle(tStdout);
834 if (tStderr != 0)
835 CloseHandle(tStderr);
837 if (pproc->lerrno)
838 return(-1);
839 else
840 return(0);
845 * Purpose: collects output from child process and returns results
847 * Description:
849 * Returns:
851 * Notes/Dependencies:
853 long
854 process_file_io(
855 HANDLE proc)
857 sub_process *pproc;
858 HANDLE childhand;
859 DWORD wait_return;
860 BOOL GetExitCodeResult;
861 DWORD ierr;
863 if (proc == NULL)
864 pproc = process_wait_for_any_private();
865 else
866 pproc = (sub_process *)proc;
868 /* some sort of internal error */
869 if (!pproc)
870 return -1;
872 childhand = (HANDLE) pproc->pid;
875 * This function is poorly named, and could also be used just to wait
876 * for child death if you're doing your own pipe I/O. If that is
877 * the case, close the pipe handles here.
879 if (pproc->sv_stdin[0]) {
880 CloseHandle((HANDLE)pproc->sv_stdin[0]);
881 pproc->sv_stdin[0] = 0;
883 if (pproc->sv_stdout[0]) {
884 CloseHandle((HANDLE)pproc->sv_stdout[0]);
885 pproc->sv_stdout[0] = 0;
887 if (pproc->sv_stderr[0]) {
888 CloseHandle((HANDLE)pproc->sv_stderr[0]);
889 pproc->sv_stderr[0] = 0;
893 * Wait for the child process to exit
896 wait_return = WaitForSingleObject(childhand, INFINITE);
898 if (wait_return != WAIT_OBJECT_0) {
899 /* map_windows32_error_to_string(GetLastError());*/
900 pproc->last_err = GetLastError();
901 pproc->lerrno = E_SCALL;
902 goto done2;
905 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
906 if (ierr == CONTROL_C_EXIT) {
907 pproc->signal = SIGINT;
908 } else {
909 pproc->exit_code = ierr;
911 if (GetExitCodeResult == FALSE) {
912 pproc->last_err = GetLastError();
913 pproc->lerrno = E_SCALL;
916 done2:
917 if (pproc->lerrno)
918 return(-1);
919 else
920 return(0);
925 * Description: Clean up any leftover handles, etc. It is up to the
926 * caller to manage and free the input, ouput, and stderr buffers.
928 void
929 process_cleanup(
930 HANDLE proc)
932 sub_process *pproc = (sub_process *)proc;
933 int i;
935 if (pproc->using_pipes) {
936 for (i= 0; i <= 1; i++) {
937 if ((HANDLE)pproc->sv_stdin[i])
938 CloseHandle((HANDLE)pproc->sv_stdin[i]);
939 if ((HANDLE)pproc->sv_stdout[i])
940 CloseHandle((HANDLE)pproc->sv_stdout[i]);
941 if ((HANDLE)pproc->sv_stderr[i])
942 CloseHandle((HANDLE)pproc->sv_stderr[i]);
945 if ((HANDLE)pproc->pid)
946 CloseHandle((HANDLE)pproc->pid);
948 free(pproc);
953 * Description:
954 * Create a command line buffer to pass to CreateProcess
956 * Returns: the buffer or NULL for failure
957 * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ...
958 * Otherwise: argv[0] argv[1] argv[2] ...
960 * Notes/Dependencies:
961 * CreateProcess does not take an argv, so this command creates a
962 * command line for the executable.
965 static char *
966 make_command_line( char *shell_name, char *full_exec_path, char **argv)
968 int argc = 0;
969 char** argvi;
970 int* enclose_in_quotes = NULL;
971 int* enclose_in_quotes_i;
972 unsigned int bytes_required = 0;
973 char* command_line;
974 char* command_line_i;
975 int cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */
976 int have_sh = 0; /* HAVE_CYGWIN_SHELL */
978 #ifdef HAVE_CYGWIN_SHELL
979 have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe"));
980 cygwin_mode = 1;
981 #endif
983 if (shell_name && full_exec_path) {
984 bytes_required
985 = strlen(shell_name) + 1 + strlen(full_exec_path);
987 * Skip argv[0] if any, when shell_name is given.
989 if (*argv) argv++;
991 * Add one for the intervening space.
993 if (*argv) bytes_required++;
996 argvi = argv;
997 while (*(argvi++)) argc++;
999 if (argc) {
1000 enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));
1002 if (!enclose_in_quotes) {
1003 return NULL;
1007 /* We have to make one pass through each argv[i] to see if we need
1008 * to enclose it in ", so we might as well figure out how much
1009 * memory we'll need on the same pass.
1012 argvi = argv;
1013 enclose_in_quotes_i = enclose_in_quotes;
1014 while(*argvi) {
1015 char* p = *argvi;
1016 unsigned int backslash_count = 0;
1019 * We have to enclose empty arguments in ".
1021 if (!(*p)) *enclose_in_quotes_i = 1;
1023 while(*p) {
1024 switch (*p) {
1025 case '\"':
1027 * We have to insert a backslash for each "
1028 * and each \ that precedes the ".
1030 bytes_required += (backslash_count + 1);
1031 backslash_count = 0;
1032 break;
1034 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1035 case '\\':
1036 backslash_count++;
1037 break;
1038 #endif
1040 * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
1041 * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
1042 * that argv in always equals argv out. This was removed. Say you have
1043 * such a program named glob.exe. You enter
1044 * glob '*'
1045 * at the sh command prompt. Obviously the intent is to make glob do the
1046 * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?',
1047 * then the command line that glob would see would be
1048 * glob "*"
1049 * and the _setargv in SETARGV.OBJ would _not_ expand the *.
1051 case ' ':
1052 case '\t':
1053 *enclose_in_quotes_i = 1;
1054 /* fall through */
1056 default:
1057 backslash_count = 0;
1058 break;
1062 * Add one for each character in argv[i].
1064 bytes_required++;
1066 p++;
1069 if (*enclose_in_quotes_i) {
1071 * Add one for each enclosing ",
1072 * and one for each \ that precedes the
1073 * closing ".
1075 bytes_required += (backslash_count + 2);
1079 * Add one for the intervening space.
1081 if (*(++argvi)) bytes_required++;
1082 enclose_in_quotes_i++;
1086 * Add one for the terminating NULL.
1088 bytes_required++;
1090 command_line = (char*) malloc(bytes_required);
1092 if (!command_line) {
1093 if (enclose_in_quotes) free(enclose_in_quotes);
1094 return NULL;
1097 command_line_i = command_line;
1099 if (shell_name && full_exec_path) {
1100 while(*shell_name) {
1101 *(command_line_i++) = *(shell_name++);
1104 *(command_line_i++) = ' ';
1106 while(*full_exec_path) {
1107 *(command_line_i++) = *(full_exec_path++);
1110 if (*argv) {
1111 *(command_line_i++) = ' ';
1115 argvi = argv;
1116 enclose_in_quotes_i = enclose_in_quotes;
1118 while(*argvi) {
1119 char* p = *argvi;
1120 unsigned int backslash_count = 0;
1122 if (*enclose_in_quotes_i) {
1123 *(command_line_i++) = '\"';
1126 while(*p) {
1127 if (*p == '\"') {
1128 if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */
1129 /* instead of a \", cygwin likes "" */
1130 *(command_line_i++) = '\"';
1131 } else {
1134 * We have to insert a backslash for the "
1135 * and each \ that precedes the ".
1137 backslash_count++;
1139 while(backslash_count) {
1140 *(command_line_i++) = '\\';
1141 backslash_count--;
1144 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1145 } else if (*p == '\\') {
1146 backslash_count++;
1147 } else {
1148 backslash_count = 0;
1149 #endif
1153 * Copy the character.
1155 *(command_line_i++) = *(p++);
1158 if (*enclose_in_quotes_i) {
1159 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1161 * Add one \ for each \ that precedes the
1162 * closing ".
1164 while(backslash_count--) {
1165 *(command_line_i++) = '\\';
1167 #endif
1168 *(command_line_i++) = '\"';
1172 * Append an intervening space.
1174 if (*(++argvi)) {
1175 *(command_line_i++) = ' ';
1178 enclose_in_quotes_i++;
1182 * Append the terminating NULL.
1184 *command_line_i = '\0';
1186 if (enclose_in_quotes) free(enclose_in_quotes);
1187 return command_line;
1191 * Description: Given an argv and optional envp, launch the process
1192 * using the default stdin, stdout, and stderr handles.
1193 * Also, register process so that process_wait_for_any_private()
1194 * can be used via process_file_io(NULL) or
1195 * process_wait_for_any().
1197 * Returns:
1199 * Notes/Dependencies:
1201 HANDLE
1202 process_easy(
1203 char **argv,
1204 char **envp)
1206 HANDLE hIn;
1207 HANDLE hOut;
1208 HANDLE hErr;
1209 HANDLE hProcess;
1211 if (proc_index >= MAXIMUM_WAIT_OBJECTS) {
1212 DB (DB_JOBS, ("process_easy: All process slots used up\n"));
1213 return INVALID_HANDLE_VALUE;
1215 if (DuplicateHandle(GetCurrentProcess(),
1216 GetStdHandle(STD_INPUT_HANDLE),
1217 GetCurrentProcess(),
1218 &hIn,
1220 TRUE,
1221 DUPLICATE_SAME_ACCESS) == FALSE) {
1222 fprintf(stderr,
1223 "process_easy: DuplicateHandle(In) failed (e=%ld)\n",
1224 GetLastError());
1225 return INVALID_HANDLE_VALUE;
1227 if (DuplicateHandle(GetCurrentProcess(),
1228 GetStdHandle(STD_OUTPUT_HANDLE),
1229 GetCurrentProcess(),
1230 &hOut,
1232 TRUE,
1233 DUPLICATE_SAME_ACCESS) == FALSE) {
1234 fprintf(stderr,
1235 "process_easy: DuplicateHandle(Out) failed (e=%ld)\n",
1236 GetLastError());
1237 return INVALID_HANDLE_VALUE;
1239 if (DuplicateHandle(GetCurrentProcess(),
1240 GetStdHandle(STD_ERROR_HANDLE),
1241 GetCurrentProcess(),
1242 &hErr,
1244 TRUE,
1245 DUPLICATE_SAME_ACCESS) == FALSE) {
1246 fprintf(stderr,
1247 "process_easy: DuplicateHandle(Err) failed (e=%ld)\n",
1248 GetLastError());
1249 return INVALID_HANDLE_VALUE;
1252 hProcess = process_init_fd(hIn, hOut, hErr);
1254 if (process_begin(hProcess, argv, envp, argv[0], NULL)) {
1255 fake_exits_pending++;
1256 /* process_begin() failed: make a note of that. */
1257 if (!((sub_process*) hProcess)->last_err)
1258 ((sub_process*) hProcess)->last_err = -1;
1259 ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);
1261 /* close up unused handles */
1262 CloseHandle(hIn);
1263 CloseHandle(hOut);
1264 CloseHandle(hErr);
1267 process_register(hProcess);
1269 return hProcess;