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
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/>. */
21 #include <process.h> /* for msvc _beginthreadex, _endthreadex */
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
{
36 intptr_t sv_stdout
[2];
37 intptr_t sv_stderr
[2];
42 volatile DWORD outcnt
;
44 volatile DWORD errcnt
;
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
62 process_adjust_wait_state(sub_process
* pproc
)
69 for (i
= 0; i
< proc_index
; i
++)
70 if (proc_array
[i
]->pid
== pproc
->pid
)
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.
86 process_wait_for_any_private(void)
88 HANDLE handles
[MAXIMUM_WAIT_OBJECTS
];
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
)
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
;
108 fake_exits_pending
--;
109 retval
= !WAIT_FAILED
;
113 /* return pointer to process */
114 if (retval
!= WAIT_FAILED
) {
115 sub_process
* pproc
= proc_array
[which
];
116 process_adjust_wait_state(pproc
);
123 * Terminate a process.
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 :-(
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)
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(...);
164 * x = process_init_fd();
165 * process_register(x);
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
178 process_wait_for_any(void)
180 sub_process
* pproc
= process_wait_for_any_private();
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
);
195 process_signal(HANDLE proc
)
197 if (proc
== INVALID_HANDLE_VALUE
) return 0;
198 return (((sub_process
*)proc
)->signal
);
202 process_last_err(HANDLE proc
)
204 if (proc
== INVALID_HANDLE_VALUE
) return ERROR_INVALID_HANDLE
;
205 return (((sub_process
*)proc
)->last_err
);
209 process_exit_code(HANDLE proc
)
211 if (proc
== INVALID_HANDLE_VALUE
) return EXIT_FAILURE
;
212 return (((sub_process
*)proc
)->exit_code
);
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.
223 process_outbuf(HANDLE proc)
225 return (((sub_process *)proc)->outp);
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);
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];
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;
325 return((HANDLE
)pproc
);
330 process_init_fd(HANDLE stdinh
, HANDLE stdouth
, HANDLE stderrh
)
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
);
352 find_file(const char *exec_path
, const char *path_var
,
353 char *full_fname
, DWORD full_len
)
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
382 || (req_len
= SearchPath (NULL
, fname
, NULL
, full_len
,
383 full_fname
, NULL
)) > 0)
384 && req_len
<= full_len
386 CreateFile(full_fname
,
388 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
391 FILE_ATTRIBUTE_NORMAL
,
392 NULL
)) != INVALID_HANDLE_VALUE
) {
399 return INVALID_HANDLE_VALUE
;
404 * Description: Create the child process to be helped
406 * Returns: success <=> 0
408 * Notes/Dependencies:
418 sub_process
*pproc
= (sub_process
*)proc
;
419 char *shell_name
= 0;
420 int file_not_found
=0;
422 char exec_fname
[MAX_PATH
];
423 const char *path_var
= NULL
;
426 DWORD bytes_returned
;
429 STARTUPINFO startInfo
;
430 PROCESS_INFORMATION procInfo
;
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
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. */
446 for (ep
= envp
; *ep
; ep
++) {
447 if (strncmp (*ep
, "PATH=", 5) == 0
448 || strncmp (*ep
, "Path=", 5) == 0) {
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
) {
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
);
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
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');
491 p
= strchr(buf
, '\r');
496 * Find base name of shell
498 shell_name
= strrchr( buf
, '/');
502 shell_name
= &buf
[2];/* skipping "#!" */
506 CloseHandle(exec_handle
);
512 command_line
= make_command_line( shell_name
, exec_path
, argv
);
514 command_line
= make_command_line( shell_name
, exec_fname
, argv
);
516 if ( command_line
== NULL
) {
518 pproc
->lerrno
= E_NO_MEM
;
523 if (arr2envblk(envp
, &envblk
) ==FALSE
) {
525 pproc
->lerrno
= E_NO_MEM
;
526 free( command_line
);
531 if ((shell_name
) || (file_not_found
)) {
532 exec_path
= 0; /* Search for the program in %Path% */
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];
551 if (envblk
) free(envblk
);
554 DB (DB_JOBS
, ("CreateProcess(%s,%s,...)\n",
555 exec_path
? exec_path
: "NULL",
556 command_line
? command_line
: "NULL"));
561 0, /* default security attributes for thread */
562 TRUE
, /* inherit handles (e.g. helper pipes, oserv socket) */
565 0, /* default starting directory */
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
);
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
);
600 proc_stdin_thread(sub_process
*pproc
)
604 if (WriteFile( (HANDLE
) pproc
->sv_stdin
[0], pproc
->inp
, pproc
->incnt
,
605 &in_done
, NULL
) == FALSE
)
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
;
616 return 0; // for compiler warnings only.. not reached
620 proc_stdout_thread(sub_process
*pproc
)
622 DWORD bufsize
= 1024;
625 pproc
->outp
= malloc(bufsize
);
626 if (pproc
->outp
== NULL
)
631 if (ReadFile( (HANDLE
)pproc
->sv_stdout
[0], &c
, 1, &nread
, NULL
)
633 /* map_windows32_error_to_string(GetLastError());*/
638 if (pproc
->outcnt
+ nread
> bufsize
) {
639 bufsize
+= nread
+ 512;
640 pproc
->outp
= realloc(pproc
->outp
, bufsize
);
641 if (pproc
->outp
== NULL
) {
646 pproc
->outp
[pproc
->outcnt
++] = c
;
652 proc_stderr_thread(sub_process
*pproc
)
654 DWORD bufsize
= 1024;
657 pproc
->errp
= malloc(bufsize
);
658 if (pproc
->errp
== NULL
)
663 if (ReadFile( (HANDLE
)pproc
->sv_stderr
[0], &c
, 1, &nread
, NULL
) == FALSE
) {
664 map_windows32_error_to_string(GetLastError());
669 if (pproc
->errcnt
+ nread
> bufsize
) {
670 bufsize
+= nread
+ 512;
671 pproc
->errp
= realloc(pproc
->errp
, bufsize
);
672 if (pproc
->errp
== NULL
) {
677 pproc
->errp
[pproc
->errcnt
++] = c
;
684 * Purpose: collects output from child process and returns results
690 * Notes/Dependencies:
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
;
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
;
717 CloseHandle((HANDLE
)pproc
->sv_stdin
[0]);
718 pproc
->sv_stdin
[0] = 0;
720 tStdin
= (HANDLE
) _beginthreadex( 0, 1024,
721 (unsigned (__stdcall
*) (void *))proc_stdin_thread
,
724 pproc
->last_err
= GetLastError();
725 pproc
->lerrno
= E_SCALL
;
731 * Assume child will produce stdout and stderr
733 tStdout
= (HANDLE
) _beginthreadex( 0, 1024,
734 (unsigned (__stdcall
*) (void *))proc_stdout_thread
, pproc
, 0,
736 tStderr
= (HANDLE
) _beginthreadex( 0, 1024,
737 (unsigned (__stdcall
*) (void *))proc_stderr_thread
, pproc
, 0,
740 if (tStdout
== 0 || tStderr
== 0) {
742 pproc
->last_err
= GetLastError();
743 pproc
->lerrno
= E_SCALL
;
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
) {
755 wait_list
[wait_count
++] = tStdin
;
758 wait_list
[wait_count
++] = tStdout
;
761 wait_list
[wait_count
++] = tStderr
;
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
;
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;
788 } else if (ready_hand
== tStdout
) {
790 CloseHandle((HANDLE
)pproc
->sv_stdout
[0]);
791 pproc
->sv_stdout
[0] = 0;
792 CloseHandle(tStdout
);
796 } else if (ready_hand
== tStderr
) {
798 CloseHandle((HANDLE
)pproc
->sv_stderr
[0]);
799 pproc
->sv_stderr
[0] = 0;
800 CloseHandle(tStderr
);
804 } else if (ready_hand
== childhand
) {
807 GetExitCodeResult
= GetExitCodeProcess(childhand
, &ierr
);
808 if (ierr
== CONTROL_C_EXIT
) {
809 pproc
->signal
= SIGINT
;
811 pproc
->exit_code
= ierr
;
813 if (GetExitCodeResult
== FALSE
) {
814 pproc
->last_err
= GetLastError();
815 pproc
->lerrno
= E_SCALL
;
822 /* ?? Got back a handle we didn't query ?? */
824 pproc
->lerrno
= E_FAIL
;
833 CloseHandle(tStdout
);
835 CloseHandle(tStderr
);
845 * Purpose: collects output from child process and returns results
851 * Notes/Dependencies:
860 BOOL GetExitCodeResult
;
864 pproc
= process_wait_for_any_private();
866 pproc
= (sub_process
*)proc
;
868 /* some sort of internal error */
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
;
905 GetExitCodeResult
= GetExitCodeProcess(childhand
, &ierr
);
906 if (ierr
== CONTROL_C_EXIT
) {
907 pproc
->signal
= SIGINT
;
909 pproc
->exit_code
= ierr
;
911 if (GetExitCodeResult
== FALSE
) {
912 pproc
->last_err
= GetLastError();
913 pproc
->lerrno
= E_SCALL
;
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.
932 sub_process
*pproc
= (sub_process
*)proc
;
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
);
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.
966 make_command_line( char *shell_name
, char *full_exec_path
, char **argv
)
970 int* enclose_in_quotes
= NULL
;
971 int* enclose_in_quotes_i
;
972 unsigned int bytes_required
= 0;
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"));
983 if (shell_name
&& full_exec_path
) {
985 = strlen(shell_name
) + 1 + strlen(full_exec_path
);
987 * Skip argv[0] if any, when shell_name is given.
991 * Add one for the intervening space.
993 if (*argv
) bytes_required
++;
997 while (*(argvi
++)) argc
++;
1000 enclose_in_quotes
= (int*) calloc(1, argc
* sizeof(int));
1002 if (!enclose_in_quotes
) {
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.
1013 enclose_in_quotes_i
= enclose_in_quotes
;
1016 unsigned int backslash_count
= 0;
1019 * We have to enclose empty arguments in ".
1021 if (!(*p
)) *enclose_in_quotes_i
= 1;
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;
1034 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
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
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
1049 * and the _setargv in SETARGV.OBJ would _not_ expand the *.
1053 *enclose_in_quotes_i
= 1;
1057 backslash_count
= 0;
1062 * Add one for each character in argv[i].
1069 if (*enclose_in_quotes_i
) {
1071 * Add one for each enclosing ",
1072 * and one for each \ that precedes the
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.
1090 command_line
= (char*) malloc(bytes_required
);
1092 if (!command_line
) {
1093 if (enclose_in_quotes
) free(enclose_in_quotes
);
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
++);
1111 *(command_line_i
++) = ' ';
1116 enclose_in_quotes_i
= enclose_in_quotes
;
1120 unsigned int backslash_count
= 0;
1122 if (*enclose_in_quotes_i
) {
1123 *(command_line_i
++) = '\"';
1128 if (cygwin_mode
&& have_sh
) { /* HAVE_CYGWIN_SHELL */
1129 /* instead of a \", cygwin likes "" */
1130 *(command_line_i
++) = '\"';
1134 * We have to insert a backslash for the "
1135 * and each \ that precedes the ".
1139 while(backslash_count
) {
1140 *(command_line_i
++) = '\\';
1144 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1145 } else if (*p
== '\\') {
1148 backslash_count
= 0;
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
1164 while(backslash_count
--) {
1165 *(command_line_i
++) = '\\';
1168 *(command_line_i
++) = '\"';
1172 * Append an intervening space.
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().
1199 * Notes/Dependencies:
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(),
1221 DUPLICATE_SAME_ACCESS
) == FALSE
) {
1223 "process_easy: DuplicateHandle(In) failed (e=%ld)\n",
1225 return INVALID_HANDLE_VALUE
;
1227 if (DuplicateHandle(GetCurrentProcess(),
1228 GetStdHandle(STD_OUTPUT_HANDLE
),
1229 GetCurrentProcess(),
1233 DUPLICATE_SAME_ACCESS
) == FALSE
) {
1235 "process_easy: DuplicateHandle(Out) failed (e=%ld)\n",
1237 return INVALID_HANDLE_VALUE
;
1239 if (DuplicateHandle(GetCurrentProcess(),
1240 GetStdHandle(STD_ERROR_HANDLE
),
1241 GetCurrentProcess(),
1245 DUPLICATE_SAME_ACCESS
) == FALSE
) {
1247 "process_easy: DuplicateHandle(Err) failed (e=%ld)\n",
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 */
1267 process_register(hProcess
);