1 /* Process handling for Windows.
2 Copyright (C) 1996-2022 Free Software Foundation, Inc.
3 This file is part of GNU Make.
5 GNU Make is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3 of the License, or (at your option) any later
10 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along with
15 this program. If not, see <https://www.gnu.org/licenses/>. */
22 #include <io.h> /* for _get_osfhandle */
24 # include <stddef.h> /* for intptr_t */
29 #include <process.h> /* for msvc _beginthreadex, _endthreadex */
41 #define GMAKE_MAXIMUM_WAIT_OBJECTS (MAXIMUM_WAIT_OBJECTS * MAXIMUM_WAIT_OBJECTS)
43 /* We need to move these special-case return codes out-of-band */
44 #define GMAKE_WAIT_TIMEOUT 0xFFFF0102L
45 #define GMAKE_WAIT_ABANDONED_0 0x00080000L
47 static char *make_command_line(char *shell_name, char *exec_path, char **argv);
49 typedef struct sub_process_t {
51 intptr_t sv_stdout[2];
52 intptr_t sv_stderr[2];
57 volatile DWORD outcnt;
59 volatile DWORD errcnt;
67 /* keep track of children so we can implement a waitpid-like routine */
68 static sub_process *proc_array[GMAKE_MAXIMUM_WAIT_OBJECTS];
69 static unsigned int proc_index = 0;
70 static unsigned int fake_exits_pending = 0;
73 * Address the scalability limit intrisic to WaitForMultipleOjects by
74 * calling WaitForMultipleObjects on 64 element chunks of the input
75 * array with 0 timeout. Exit with an appropriately conditioned result
76 * or repeat again every 10 ms if no handle has signaled and the
77 * requested timeout was not zero.
79 DWORD process_wait_for_multiple_objects(
81 const HANDLE *lpHandles,
86 assert(nCount <= GMAKE_MAXIMUM_WAIT_OBJECTS);
88 if (nCount <= MAXIMUM_WAIT_OBJECTS) {
89 DWORD retVal = WaitForMultipleObjects(nCount, lpHandles, bWaitAll, dwMilliseconds);
90 return (retVal == WAIT_TIMEOUT) ? GMAKE_WAIT_TIMEOUT : retVal;
93 DWORD objectCount = nCount;
97 assert(bWaitAll == FALSE); /* This logic only works for this use case */
98 assert(dwMilliseconds == 0 || dwMilliseconds == INFINITE); /* No support for timeouts */
100 for (; objectCount > 0; blockCount++) {
101 DWORD n = objectCount <= MAXIMUM_WAIT_OBJECTS ? objectCount : MAXIMUM_WAIT_OBJECTS;
103 retVal = WaitForMultipleObjects(n, &lpHandles[blockCount * MAXIMUM_WAIT_OBJECTS],
107 retVal = GMAKE_WAIT_TIMEOUT;
111 fprintf(stderr,"WaitForMultipleOjbects failed waiting with error %lu\n", GetLastError());
114 if (retVal >= WAIT_ABANDONED_0) {
115 assert(retVal < WAIT_ABANDONED_0 + MAXIMUM_WAIT_OBJECTS);
116 retVal += blockCount * MAXIMUM_WAIT_OBJECTS - WAIT_ABANDONED_0 + GMAKE_WAIT_ABANDONED_0;
118 assert(retVal < WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS);
119 retVal += blockCount * MAXIMUM_WAIT_OBJECTS;
128 if (dwMilliseconds == 0) return retVal;
130 Sleep(10); /* Sleep for 10 ms */
136 * Fill a HANDLE list with handles to wait for.
139 process_set_handles(HANDLE *handles)
144 /* Build array of handles to wait for */
145 for (i = 0; i < proc_index; i++) {
146 /* Don't wait on child processes that have already finished */
147 if (fake_exits_pending && proc_array[i]->exit_code)
150 handles[count++] = (HANDLE) proc_array[i]->pid;
157 * When a process has been waited for, adjust the wait state
158 * array so that we don't wait for it again
161 process_adjust_wait_state(sub_process* pproc)
168 for (i = 0; i < proc_index; i++)
169 if (proc_array[i]->pid == pproc->pid)
172 if (i < proc_index) {
175 memmove(&proc_array[i], &proc_array[i+1],
176 (proc_index-i) * sizeof(sub_process*));
177 proc_array[proc_index] = NULL;
182 * Waits for any of the registered child processes to finish.
185 process_wait_for_any_private(int block, DWORD* pdwWaitStatus)
187 HANDLE handles[GMAKE_MAXIMUM_WAIT_OBJECTS];
194 /* build array of handles to wait for */
195 for (i = 0; i < proc_index; i++) {
196 handles[i] = (HANDLE) proc_array[i]->pid;
198 if (fake_exits_pending && proc_array[i]->exit_code)
202 /* wait for someone to exit */
203 if (!fake_exits_pending) {
204 retval = process_wait_for_multiple_objects(proc_index, handles, FALSE, (block ? INFINITE : 0));
205 which = retval - WAIT_OBJECT_0;
207 fake_exits_pending--;
208 retval = !WAIT_FAILED;
212 /* If the pointer is not NULL, set the wait status result variable. */
214 *pdwWaitStatus = (retval == GMAKE_WAIT_TIMEOUT) ? WAIT_TIMEOUT : retval;
216 /* return pointer to process */
217 if ((retval == GMAKE_WAIT_TIMEOUT) || (retval == WAIT_FAILED)) {
221 sub_process* pproc = proc_array[which];
222 process_adjust_wait_state(pproc);
228 * Terminate a process.
231 process_kill(HANDLE proc, int signal)
233 sub_process* pproc = (sub_process*) proc;
234 pproc->signal = signal;
235 return (TerminateProcess((HANDLE) pproc->pid, signal));
239 * Returns true when we have no more available slots in our process table.
244 extern int shell_function_pid;
246 /* Reserve slots for jobserver_semaphore if we have one and the shell function if not active */
247 return(proc_index >= GMAKE_MAXIMUM_WAIT_OBJECTS - jobserver_enabled() - (shell_function_pid == 0));
251 * Returns the maximum number of job slots we can support when using the jobserver.
254 process_table_usable_size()
256 /* Reserve slots for jobserver_semaphore and shell function */
257 return(GMAKE_MAXIMUM_WAIT_OBJECTS - 2);
261 * Returns the actual size of the process table.
264 process_table_actual_size()
266 return(GMAKE_MAXIMUM_WAIT_OBJECTS);
270 * Use this function to register processes you wish to wait for by
271 * calling process_file_io(NULL) or process_wait_any(). This must be done
272 * because it is possible for callers of this library to reuse the same
273 * handle for multiple processes launches :-(
276 process_register(HANDLE proc)
278 assert(proc_index < GMAKE_MAXIMUM_WAIT_OBJECTS);
279 proc_array[proc_index++] = (sub_process *) proc;
283 * Public function which works kind of like waitpid(). Wait for any
284 * of the children to die and return results. To call this function,
285 * you must do 1 of things:
287 * x = process_easy(...);
291 * x = process_init_fd();
292 * process_register(x);
296 * x = process_init();
297 * process_register(x);
299 * You must NOT then call process_pipe_io() because this function is
300 * not capable of handling automatic notification of any child
305 process_wait_for_any(int block, DWORD* pdwWaitStatus)
307 sub_process* pproc = process_wait_for_any_private(block, pdwWaitStatus);
313 * Ouch! can't tell caller if this fails directly. Caller
314 * will have to use process_last_err()
316 (void) process_file_io(pproc);
317 return ((HANDLE) pproc);
322 process_signal(HANDLE proc)
324 if (proc == INVALID_HANDLE_VALUE) return 0;
325 return (((sub_process *)proc)->signal);
329 process_last_err(HANDLE proc)
331 if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
332 return (((sub_process *)proc)->last_err);
336 process_exit_code(HANDLE proc)
338 if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE;
339 return (((sub_process *)proc)->exit_code);
344 All the following functions are currently unused.
345 All of them would crash gmake if called with argument INVALID_HANDLE_VALUE.
346 Hence whoever wants to use one of this functions must invent and implement
347 a reasonable error handling for this function.
350 process_outbuf(HANDLE proc)
352 return (((sub_process *)proc)->outp);
356 process_errbuf(HANDLE proc)
358 return (((sub_process *)proc)->errp);
362 process_outcnt(HANDLE proc)
364 return (((sub_process *)proc)->outcnt);
368 process_errcnt(HANDLE proc)
370 return (((sub_process *)proc)->errcnt);
374 process_pipes(HANDLE proc, int pipes[3])
376 pipes[0] = ((sub_process *)proc)->sv_stdin[0];
377 pipes[1] = ((sub_process *)proc)->sv_stdout[0];
378 pipes[2] = ((sub_process *)proc)->sv_stderr[0];
388 * open file descriptors for attaching stdin/stdout/sterr
390 HANDLE stdin_pipes[2];
391 HANDLE stdout_pipes[2];
392 HANDLE stderr_pipes[2];
393 SECURITY_ATTRIBUTES inherit;
394 BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
396 pproc = malloc(sizeof(*pproc));
397 memset(pproc, 0, sizeof(*pproc));
399 /* We can't use NULL for lpSecurityDescriptor because that
400 uses the default security descriptor of the calling process.
401 Instead we use a security descriptor with no DACL. This
402 allows nonrestricted access to the associated objects. */
404 if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),
405 SECURITY_DESCRIPTOR_REVISION)) {
406 pproc->last_err = GetLastError();
407 pproc->lerrno = E_SCALL;
408 return((HANDLE)pproc);
411 inherit.nLength = sizeof(inherit);
412 inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);
413 inherit.bInheritHandle = TRUE;
415 /* By convention, parent gets pipe[0], and child gets pipe[1].
416 This means the READ side of stdin pipe goes into pipe[1] and the
417 WRITE side of the stdout and stderr pipes go into pipe[1]. */
418 if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||
419 CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||
420 CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {
422 pproc->last_err = GetLastError();
423 pproc->lerrno = E_SCALL;
424 return((HANDLE)pproc);
427 /* Mark the parent sides of the pipes as non-inheritable. */
428 if (SetHandleInformation(stdin_pipes[0],
429 HANDLE_FLAG_INHERIT, 0) == FALSE ||
430 SetHandleInformation(stdout_pipes[0],
431 HANDLE_FLAG_INHERIT, 0) == FALSE ||
432 SetHandleInformation(stderr_pipes[0],
433 HANDLE_FLAG_INHERIT, 0) == FALSE) {
435 pproc->last_err = GetLastError();
436 pproc->lerrno = E_SCALL;
437 return((HANDLE)pproc);
439 pproc->sv_stdin[0] = (intptr_t) stdin_pipes[0];
440 pproc->sv_stdin[1] = (intptr_t) stdin_pipes[1];
441 pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0];
442 pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1];
443 pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0];
444 pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1];
446 pproc->using_pipes = 1;
450 return((HANDLE)pproc);
455 process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)
459 pproc = malloc(sizeof(*pproc));
461 memset(pproc, 0, sizeof(*pproc));
464 * Just pass the provided file handles to the 'child
465 * side' of the pipe, bypassing pipes altogether.
467 pproc->sv_stdin[1] = (intptr_t) stdinh;
468 pproc->sv_stdout[1] = (intptr_t) stdouth;
469 pproc->sv_stderr[1] = (intptr_t) stderrh;
471 pproc->last_err = pproc->lerrno = 0;
474 return((HANDLE)pproc);
479 find_file(const char *exec_path, const char *path_var,
480 char *full_fname, DWORD full_len)
487 static const char *extensions[] =
488 /* Should .com come before no-extension case? */
489 { ".exe", ".cmd", ".bat", "", ".com", NULL };
491 fname = xmalloc(strlen(exec_path) + 5);
492 strcpy(fname, exec_path);
493 ext = fname + strlen(fname);
495 for (i = 0; extensions[i]; i++) {
496 strcpy(ext, extensions[i]);
497 if (((req_len = SearchPath (path_var, fname, NULL, full_len,
498 full_fname, NULL)) > 0
499 /* For compatibility with previous code, which
500 used OpenFile, and with Windows operation in
501 general, also look in various default
502 locations, such as Windows directory and
503 Windows System directory. Warning: this also
504 searches PATH in the Make's environment, which
505 might not be what the Makefile wants, but it
506 seems to be OK as a fallback, after the
507 previous SearchPath failed to find on child's
509 || (req_len = SearchPath (NULL, fname, NULL, full_len,
510 full_fname, NULL)) > 0)
511 && req_len <= full_len
513 CreateFile(full_fname,
515 FILE_SHARE_READ | FILE_SHARE_WRITE,
518 FILE_ATTRIBUTE_NORMAL,
519 NULL)) != INVALID_HANDLE_VALUE) {
526 return INVALID_HANDLE_VALUE;
530 * Return non-zero of FNAME specifies a batch file and its name
531 * includes embedded whitespace.
535 batch_file_with_spaces(const char *fname)
537 size_t fnlen = strlen(fname);
540 && (_strnicmp(fname + fnlen - 4, ".bat", 4) == 0
541 || _strnicmp(fname + fnlen - 4, ".cmd", 4) == 0)
542 /* The set of characters in the 2nd arg to strpbrk
543 should be the same one used by make_command_line
544 below to decide whether an argv[] element needs
546 && strpbrk(fname, " \t") != NULL);
551 * Description: Create the child process to be helped
553 * Returns: success <=> 0
555 * Notes/Dependencies:
565 sub_process *pproc = (sub_process *)proc;
566 char *shell_name = 0;
567 int file_not_found=0;
569 char exec_fname[MAX_PATH];
570 const char *path_var = NULL;
573 DWORD bytes_returned;
576 STARTUPINFO startInfo;
577 PROCESS_INFORMATION procInfo;
579 size_t envsize_needed = 0;
580 int pass_null_exec_path = 0;
583 * Shell script detection... if the exec_path starts with #! then
584 * we want to exec shell-script-name exec-path, not just exec-path
585 * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not
586 * hard-code the path to the shell or perl or whatever: Instead, we
587 * assume it's in the path somewhere (generally, the NT tools
591 /* Use the Makefile's value of PATH to look for the program to
592 execute, because it could be different from Make's PATH
593 (e.g., if the target sets its own value. */
595 for (ep = envp; *ep; ep++) {
596 if (strncmp (*ep, "PATH=", 5) == 0
597 || strncmp (*ep, "Path=", 5) == 0) {
602 exec_handle = find_file(exec_path, path_var,
603 exec_fname, sizeof(exec_fname));
606 * If we couldn't open the file, just assume that Windows will be
607 * somehow able to find and execute it. If the first character
608 * of the command is '/', assume they set SHELL to a Unixy shell
609 * that have some magic mounts known only to it, and run the whole
610 * command via $SHELL -c "COMMAND" instead.
612 if (exec_handle == INVALID_HANDLE_VALUE) {
613 if (exec_path[0] == '/') {
618 strcpy(buf, variable_expand ("$(SHELL)"));
619 shell_name = &buf[0];
620 strcpy(exec_fname, "-c");
621 /* Construct a single command string in argv[0]. */
623 arglen += strlen(*argvi) + 1;
626 new_argv0 = xmalloc(arglen + 1);
628 for (argvi = argv; *argvi; argvi++) {
629 strcat(new_argv0, *argvi);
630 strcat(new_argv0, " ");
632 /* Remove the extra blank at the end. */
633 new_argv0[arglen-1] = '\0';
642 /* Attempt to read the first line of the file */
643 if (ReadFile( exec_handle,
644 buf, sizeof(buf) - 1, /* leave room for trailing NULL */
645 &bytes_returned, 0) == FALSE || bytes_returned < 2) {
647 pproc->last_err = GetLastError();
648 pproc->lerrno = E_IO;
649 CloseHandle(exec_handle);
652 if (buf[0] == '#' && buf[1] == '!') {
654 * This is a shell script... Change the command line from
655 * exec_path args to shell_name exec_path args
659 /* Make sure buf is NULL terminated */
660 buf[bytes_returned] = 0;
662 * Depending on the file system type, etc. the first line
663 * of the shell script may end with newline or newline-carriage-return
664 * Whatever it ends with, cut it off.
666 p= strchr(buf, '\n');
669 p = strchr(buf, '\r');
674 * Find base name of shell
676 shell_name = strrchr( buf, '/');
680 shell_name = &buf[2];/* skipping "#!" */
684 CloseHandle(exec_handle);
690 command_line = make_command_line( shell_name, exec_path, argv);
692 /* If exec_fname includes whitespace, CreateProcess
693 behaves erratically and unreliably, and often fails
694 if argv[0] also includes whitespace (and thus will
695 be quoted by make_command_line below). So in that
696 case, we don't pass exec_fname as the 1st arg to
697 CreateProcess, but instead replace argv[0] with
698 exec_fname (to keep its leading directories and
699 extension as found by find_file), and pass NULL to
700 CreateProcess as its 1st arg. This works around
701 the bugs in CreateProcess, which are probably
702 caused by its passing the command to cmd.exe with
703 some incorrect quoting. */
705 && batch_file_with_spaces(exec_fname)
706 && _stricmp(exec_path, argv[0]) == 0) {
711 pass_null_exec_path = 1;
712 /* Rewrite argv[] replacing argv[0] with exec_fname. */
713 for (argvi = argv + 1, arglen = strlen(exec_fname) + 1;
716 arglen += strlen(*argvi) + 1;
718 new_argv = xmalloc(arglen);
719 p = strcpy(new_argv, exec_fname) + strlen(exec_fname) + 1;
720 for (argvi = argv + 1, i = 1; *argvi; argvi++, i++) {
723 p += strlen(*argvi) + 1;
729 command_line = make_command_line( shell_name, exec_fname, argv);
732 if ( command_line == NULL ) {
734 pproc->lerrno = E_NO_MEM;
739 if (arr2envblk(envp, &envblk, &envsize_needed) == FALSE) {
740 pproc->lerrno = E_NO_MEM;
741 free( command_line );
742 if ((pproc->last_err == ERROR_INVALID_PARAMETER
743 || pproc->last_err == ERROR_MORE_DATA)
744 && envsize_needed > 32*1024) {
745 fprintf (stderr, "CreateProcess failed, probably because environment is too large (%Iu bytes).\n",
753 if (shell_name || file_not_found || pass_null_exec_path) {
754 exec_path = 0; /* Search for the program in %Path% */
756 exec_path = exec_fname;
760 * Set up inherited stdin, stdout, stderr for child
762 memset(&startInfo, '\0', sizeof(startInfo));
763 GetStartupInfo(&startInfo);
764 startInfo.dwFlags = STARTF_USESTDHANDLES;
765 startInfo.lpReserved = 0;
766 startInfo.cbReserved2 = 0;
767 startInfo.lpReserved2 = 0;
768 startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
769 startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
770 startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
776 DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n",
777 exec_path ? exec_path : "NULL",
778 command_line ? command_line : "NULL"));
783 0, /* default security attributes for thread */
784 TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */
787 0, /* default starting directory */
789 &procInfo) == FALSE) {
791 pproc->last_err = GetLastError();
792 pproc->lerrno = E_FORK;
793 fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n",
794 exec_path ? exec_path : "NULL", command_line);
796 free( command_line );
801 pproc->pid = (pid_t)procInfo.hProcess;
802 /* Close the thread handle -- we'll just watch the process */
803 CloseHandle(procInfo.hThread);
805 /* Close the halves of the pipes we don't need */
806 if ((HANDLE)pproc->sv_stdin[1] != INVALID_HANDLE_VALUE)
807 CloseHandle((HANDLE)pproc->sv_stdin[1]);
808 if ((HANDLE)pproc->sv_stdout[1] != INVALID_HANDLE_VALUE)
809 CloseHandle((HANDLE)pproc->sv_stdout[1]);
810 if ((HANDLE)pproc->sv_stderr[1] != INVALID_HANDLE_VALUE)
811 CloseHandle((HANDLE)pproc->sv_stderr[1]);
812 pproc->sv_stdin[1] = 0;
813 pproc->sv_stdout[1] = 0;
814 pproc->sv_stderr[1] = 0;
816 free( command_line );
826 proc_stdin_thread(sub_process *pproc)
830 if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,
831 &in_done, NULL) == FALSE)
833 /* This if should never be true for anonymous pipes, but gives
834 us a chance to change I/O mechanisms later. */
835 if (in_done < pproc->incnt) {
836 pproc->incnt -= in_done;
837 pproc->inp += in_done;
842 return 0; /* for compiler warnings only.. not reached. */
846 proc_stdout_thread(sub_process *pproc)
848 DWORD bufsize = 1024;
851 pproc->outp = malloc(bufsize);
852 if (pproc->outp == NULL)
857 if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL)
859 /* map_windows32_error_to_string(GetLastError());*/
864 if (pproc->outcnt + nread > bufsize) {
865 bufsize += nread + 512;
866 pproc->outp = realloc(pproc->outp, bufsize);
867 if (pproc->outp == NULL) {
872 pproc->outp[pproc->outcnt++] = c;
878 proc_stderr_thread(sub_process *pproc)
880 DWORD bufsize = 1024;
883 pproc->errp = malloc(bufsize);
884 if (pproc->errp == NULL)
889 if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {
890 map_windows32_error_to_string(GetLastError());
895 if (pproc->errcnt + nread > bufsize) {
896 bufsize += nread + 512;
897 pproc->errp = realloc(pproc->errp, bufsize);
898 if (pproc->errp == NULL) {
903 pproc->errp[pproc->errcnt++] = c;
910 * Purpose: collects output from child process and returns results
916 * Notes/Dependencies:
924 sub_process *pproc = (sub_process *)proc;
925 bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;
926 HANDLE childhand = (HANDLE) pproc->pid;
927 HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL;
928 unsigned int dwStdin, dwStdout, dwStderr;
933 bool_t child_dead = FALSE;
934 BOOL GetExitCodeResult;
937 * Create stdin thread, if needed
939 pproc->inp = stdin_data;
940 pproc->incnt = stdin_data_len;
943 CloseHandle((HANDLE)pproc->sv_stdin[0]);
944 pproc->sv_stdin[0] = 0;
946 tStdin = (HANDLE) _beginthreadex( 0, 1024,
947 (unsigned (__stdcall *) (void *))proc_stdin_thread,
950 pproc->last_err = GetLastError();
951 pproc->lerrno = E_SCALL;
957 * Assume child will produce stdout and stderr
959 tStdout = (HANDLE) _beginthreadex( 0, 1024,
960 (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,
962 tStderr = (HANDLE) _beginthreadex( 0, 1024,
963 (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,
966 if (tStdout == 0 || tStderr == 0) {
968 pproc->last_err = GetLastError();
969 pproc->lerrno = E_SCALL;
975 * Wait for all I/O to finish and for the child process to exit
978 while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
981 wait_list[wait_count++] = tStdin;
984 wait_list[wait_count++] = tStdout;
987 wait_list[wait_count++] = tStderr;
990 wait_list[wait_count++] = childhand;
993 wait_return = WaitForMultipleObjects(wait_count, wait_list,
994 FALSE, /* don't wait for all: one ready will do */
995 child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
996 one second to collect all remaining output */
998 if (wait_return == WAIT_FAILED) {
999 /* map_windows32_error_to_string(GetLastError());*/
1000 pproc->last_err = GetLastError();
1001 pproc->lerrno = E_SCALL;
1005 ready_hand = wait_list[wait_return - WAIT_OBJECT_0];
1007 if (ready_hand == tStdin) {
1008 CloseHandle((HANDLE)pproc->sv_stdin[0]);
1009 pproc->sv_stdin[0] = 0;
1010 CloseHandle(tStdin);
1014 } else if (ready_hand == tStdout) {
1016 CloseHandle((HANDLE)pproc->sv_stdout[0]);
1017 pproc->sv_stdout[0] = 0;
1018 CloseHandle(tStdout);
1022 } else if (ready_hand == tStderr) {
1024 CloseHandle((HANDLE)pproc->sv_stderr[0]);
1025 pproc->sv_stderr[0] = 0;
1026 CloseHandle(tStderr);
1030 } else if (ready_hand == childhand) {
1033 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
1034 if (ierr == CONTROL_C_EXIT) {
1035 pproc->signal = SIGINT;
1037 pproc->exit_code = ierr;
1039 if (GetExitCodeResult == FALSE) {
1040 pproc->last_err = GetLastError();
1041 pproc->lerrno = E_SCALL;
1048 /* ?? Got back a handle we didn't query ?? */
1049 pproc->last_err = 0;
1050 pproc->lerrno = E_FAIL;
1057 CloseHandle(tStdin);
1059 CloseHandle(tStdout);
1061 CloseHandle(tStderr);
1072 * Purpose: collects output from child process and returns results
1078 * Notes/Dependencies:
1087 BOOL GetExitCodeResult;
1091 pproc = process_wait_for_any_private(1, 0);
1093 pproc = (sub_process *)proc;
1095 /* some sort of internal error */
1099 childhand = (HANDLE) pproc->pid;
1102 * This function is poorly named, and could also be used just to wait
1103 * for child death if you're doing your own pipe I/O. If that is
1104 * the case, close the pipe handles here.
1106 if (pproc->sv_stdin[0]) {
1107 CloseHandle((HANDLE)pproc->sv_stdin[0]);
1108 pproc->sv_stdin[0] = 0;
1110 if (pproc->sv_stdout[0]) {
1111 CloseHandle((HANDLE)pproc->sv_stdout[0]);
1112 pproc->sv_stdout[0] = 0;
1114 if (pproc->sv_stderr[0]) {
1115 CloseHandle((HANDLE)pproc->sv_stderr[0]);
1116 pproc->sv_stderr[0] = 0;
1120 * Wait for the child process to exit
1123 wait_return = WaitForSingleObject(childhand, INFINITE);
1125 if (wait_return != WAIT_OBJECT_0) {
1126 /* map_windows32_error_to_string(GetLastError());*/
1127 pproc->last_err = GetLastError();
1128 pproc->lerrno = E_SCALL;
1132 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
1133 if (ierr == CONTROL_C_EXIT) {
1134 pproc->signal = SIGINT;
1136 pproc->exit_code = ierr;
1138 if (GetExitCodeResult == FALSE) {
1139 pproc->last_err = GetLastError();
1140 pproc->lerrno = E_SCALL;
1152 * Description: Clean up any leftover handles, etc. It is up to the
1153 * caller to manage and free the input, output, and stderr buffers.
1159 sub_process *pproc = (sub_process *)proc;
1162 if (pproc->using_pipes) {
1163 for (i= 0; i <= 1; i++) {
1164 if ((HANDLE)pproc->sv_stdin[i]
1165 && (HANDLE)pproc->sv_stdin[i] != INVALID_HANDLE_VALUE)
1166 CloseHandle((HANDLE)pproc->sv_stdin[i]);
1167 if ((HANDLE)pproc->sv_stdout[i]
1168 && (HANDLE)pproc->sv_stdout[i] != INVALID_HANDLE_VALUE)
1169 CloseHandle((HANDLE)pproc->sv_stdout[i]);
1170 if ((HANDLE)pproc->sv_stderr[i]
1171 && (HANDLE)pproc->sv_stderr[i] != INVALID_HANDLE_VALUE)
1172 CloseHandle((HANDLE)pproc->sv_stderr[i]);
1175 if ((HANDLE)pproc->pid)
1176 CloseHandle((HANDLE)pproc->pid);
1184 * Create a command line buffer to pass to CreateProcess
1186 * Returns: the buffer or NULL for failure
1187 * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ...
1188 * Otherwise: argv[0] argv[1] argv[2] ...
1190 * Notes/Dependencies:
1191 * CreateProcess does not take an argv, so this command creates a
1192 * command line for the executable.
1196 make_command_line( char *shell_name, char *full_exec_path, char **argv)
1200 int* enclose_in_quotes = NULL;
1201 int* enclose_in_quotes_i;
1202 size_t bytes_required = 0;
1204 char* command_line_i;
1205 int have_sh = 0; /* HAVE_CYGWIN_SHELL */
1206 int cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */
1208 #ifdef HAVE_CYGWIN_SHELL
1212 if (shell_name && full_exec_path) {
1213 have_sh = cygwin_mode && strstr(full_exec_path, "sh.exe");
1215 = strlen(shell_name) + 1 + strlen(full_exec_path);
1217 * Skip argv[0] if any, when shell_name is given.
1218 * The special case of "-c" in full_exec_path means
1219 * argv[0] is not the shell name, but the command string
1220 * to pass to the shell.
1222 if (*argv && strcmp(full_exec_path, "-c")) argv++;
1224 * Add one for the intervening space.
1226 if (*argv) bytes_required++;
1230 while (*(argvi++)) argc++;
1233 enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));
1235 if (!enclose_in_quotes) {
1240 /* We have to make one pass through each argv[i] to see if we need
1241 * to enclose it in ", so we might as well figure out how much
1242 * memory we'll need on the same pass.
1246 enclose_in_quotes_i = enclose_in_quotes;
1249 unsigned int backslash_count = 0;
1252 * We have to enclose empty arguments in ".
1254 if (!(*p)) *enclose_in_quotes_i = 1;
1260 * We have to insert a backslash for each "
1261 * and each \ that precedes the ".
1263 bytes_required += (backslash_count + 1);
1264 backslash_count = 0;
1267 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1273 * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
1274 * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
1275 * that argv in always equals argv out. This was removed. Say you have
1276 * such a program named glob.exe. You enter
1278 * at the sh command prompt. Obviously the intent is to make glob do the
1279 * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?',
1280 * then the command line that glob would see would be
1282 * and the _setargv in SETARGV.OBJ would _not_ expand the *.
1286 *enclose_in_quotes_i = 1;
1290 backslash_count = 0;
1295 * Add one for each character in argv[i].
1302 if (*enclose_in_quotes_i) {
1304 * Add one for each enclosing ",
1305 * and one for each \ that precedes the
1308 bytes_required += (backslash_count + 2);
1312 * Add one for the intervening space.
1314 if (*(++argvi)) bytes_required++;
1315 enclose_in_quotes_i++;
1319 * Add one for the terminating NULL.
1323 command_line = (char*) malloc(bytes_required);
1325 if (!command_line) {
1326 free(enclose_in_quotes);
1330 command_line_i = command_line;
1332 if (shell_name && full_exec_path) {
1333 while(*shell_name) {
1334 *(command_line_i++) = *(shell_name++);
1337 *(command_line_i++) = ' ';
1339 while(*full_exec_path) {
1340 *(command_line_i++) = *(full_exec_path++);
1344 *(command_line_i++) = ' ';
1349 enclose_in_quotes_i = enclose_in_quotes;
1353 unsigned int backslash_count = 0;
1355 if (*enclose_in_quotes_i) {
1356 *(command_line_i++) = '\"';
1361 if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */
1362 /* instead of a \", cygwin likes "" */
1363 *(command_line_i++) = '\"';
1367 * We have to insert a backslash for the "
1368 * and each \ that precedes the ".
1372 while(backslash_count) {
1373 *(command_line_i++) = '\\';
1377 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1378 } else if (*p == '\\') {
1381 backslash_count = 0;
1386 * Copy the character.
1388 *(command_line_i++) = *(p++);
1391 if (*enclose_in_quotes_i) {
1392 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1394 * Add one \ for each \ that precedes the
1397 while(backslash_count--) {
1398 *(command_line_i++) = '\\';
1401 *(command_line_i++) = '\"';
1405 * Append an intervening space.
1408 *(command_line_i++) = ' ';
1411 enclose_in_quotes_i++;
1415 * Append the terminating NULL.
1417 *command_line_i = '\0';
1419 free(enclose_in_quotes);
1420 return command_line;
1424 * Description: Given an argv and optional envp, launch the process
1425 * using the default stdin, stdout, and stderr handles.
1426 * Also, register process so that process_wait_for_any_private()
1427 * can be used via process_file_io(NULL) or
1428 * process_wait_for_any().
1432 * Notes/Dependencies:
1441 HANDLE hIn = INVALID_HANDLE_VALUE;
1442 HANDLE hOut = INVALID_HANDLE_VALUE;
1443 HANDLE hErr = INVALID_HANDLE_VALUE;
1444 HANDLE hProcess, tmpIn, tmpOut, tmpErr;
1447 if (process_table_full()) {
1448 DB (DB_JOBS, ("process_easy: All process slots used up\n"));
1449 return INVALID_HANDLE_VALUE;
1451 /* Standard handles returned by GetStdHandle can be NULL or
1452 INVALID_HANDLE_VALUE if the parent process closed them. If that
1453 happens, we open the null device and pass its handle to
1454 CreateProcess as the corresponding handle to inherit. */
1455 tmpIn = GetStdHandle(STD_INPUT_HANDLE);
1456 if (DuplicateHandle(GetCurrentProcess(),
1458 GetCurrentProcess(),
1462 DUPLICATE_SAME_ACCESS) == FALSE) {
1463 if ((e = GetLastError()) == ERROR_INVALID_HANDLE) {
1464 tmpIn = CreateFile("NUL", GENERIC_READ,
1465 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1466 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1467 if (tmpIn != INVALID_HANDLE_VALUE
1468 && DuplicateHandle(GetCurrentProcess(),
1470 GetCurrentProcess(),
1474 DUPLICATE_SAME_ACCESS) == FALSE)
1477 if (hIn == INVALID_HANDLE_VALUE) {
1478 fprintf(stderr, "process_easy: DuplicateHandle(In) failed (e=%ld)\n", e);
1479 return INVALID_HANDLE_VALUE;
1483 tmpOut = (HANDLE)_get_osfhandle (outfd);
1485 tmpOut = GetStdHandle (STD_OUTPUT_HANDLE);
1486 if (DuplicateHandle(GetCurrentProcess(),
1488 GetCurrentProcess(),
1492 DUPLICATE_SAME_ACCESS) == FALSE) {
1493 if ((e = GetLastError()) == ERROR_INVALID_HANDLE) {
1494 tmpOut = CreateFile("NUL", GENERIC_WRITE,
1495 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1496 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1497 if (tmpOut != INVALID_HANDLE_VALUE
1498 && DuplicateHandle(GetCurrentProcess(),
1500 GetCurrentProcess(),
1504 DUPLICATE_SAME_ACCESS) == FALSE)
1505 CloseHandle(tmpOut);
1507 if (hOut == INVALID_HANDLE_VALUE) {
1508 fprintf(stderr, "process_easy: DuplicateHandle(Out) failed (e=%ld)\n", e);
1509 return INVALID_HANDLE_VALUE;
1513 tmpErr = (HANDLE)_get_osfhandle (errfd);
1515 tmpErr = GetStdHandle(STD_ERROR_HANDLE);
1516 if (DuplicateHandle(GetCurrentProcess(),
1518 GetCurrentProcess(),
1522 DUPLICATE_SAME_ACCESS) == FALSE) {
1523 if ((e = GetLastError()) == ERROR_INVALID_HANDLE) {
1524 tmpErr = CreateFile("NUL", GENERIC_WRITE,
1525 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1526 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1527 if (tmpErr != INVALID_HANDLE_VALUE
1528 && DuplicateHandle(GetCurrentProcess(),
1530 GetCurrentProcess(),
1534 DUPLICATE_SAME_ACCESS) == FALSE)
1535 CloseHandle(tmpErr);
1537 if (hErr == INVALID_HANDLE_VALUE) {
1538 fprintf(stderr, "process_easy: DuplicateHandle(Err) failed (e=%ld)\n", e);
1539 return INVALID_HANDLE_VALUE;
1543 hProcess = process_init_fd(hIn, hOut, hErr);
1545 if (process_begin(hProcess, argv, envp, argv[0], NULL)) {
1546 fake_exits_pending++;
1547 /* process_begin() failed: make a note of that. */
1548 if (!((sub_process*) hProcess)->last_err)
1549 ((sub_process*) hProcess)->last_err = -1;
1550 ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);
1552 /* close up unused handles */
1553 if (hIn != INVALID_HANDLE_VALUE)
1555 if (hOut != INVALID_HANDLE_VALUE)
1557 if (hErr != INVALID_HANDLE_VALUE)
1561 process_register(hProcess);