Update copyright notices.
[make.git] / w32 / subproc / sub_proc.c
blobbe5f1a2cda52bc055a4bc2beaef6af6f63b731c3
1 /* Process handling for Windows.
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 2007, 2008, 2009, 2010, 2011, 2012 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;
61 /* Windows jobserver implementation variables */
62 static char jobserver_semaphore_name[MAX_PATH + 1];
63 static HANDLE jobserver_semaphore = NULL;
65 /* Open existing jobserver semaphore */
66 int open_jobserver_semaphore(const char* name)
68 jobserver_semaphore = OpenSemaphore(
69 SEMAPHORE_ALL_ACCESS, // Semaphore access setting
70 FALSE, // Child processes DON'T inherit
71 name); // Semaphore name
73 if (jobserver_semaphore == NULL)
74 return 0;
76 return 1;
79 /* Create new jobserver semaphore */
80 int create_jobserver_semaphore(int tokens)
82 sprintf(jobserver_semaphore_name, "gmake_semaphore_%d", _getpid());
84 jobserver_semaphore = CreateSemaphore(
85 NULL, // Use default security descriptor
86 tokens, // Initial count
87 tokens, // Maximum count
88 jobserver_semaphore_name); // Semaphore name
90 if (jobserver_semaphore == NULL)
91 return 0;
93 return 1;
96 /* Close jobserver semaphore */
97 void free_jobserver_semaphore()
99 if (jobserver_semaphore != NULL)
101 CloseHandle(jobserver_semaphore);
102 jobserver_semaphore = NULL;
106 /* Decrement semaphore count */
107 int acquire_jobserver_semaphore()
109 DWORD dwEvent = WaitForSingleObject(
110 jobserver_semaphore, // Handle to semaphore
111 0); // DON'T wait on semaphore
113 return (dwEvent == WAIT_OBJECT_0);
116 /* Increment semaphore count */
117 int release_jobserver_semaphore()
119 BOOL bResult = ReleaseSemaphore(
120 jobserver_semaphore, // handle to semaphore
121 1, // increase count by one
122 NULL); // not interested in previous count
124 return (bResult);
127 int has_jobserver_semaphore()
129 return (jobserver_semaphore != NULL);
132 char* get_jobserver_semaphore_name()
134 return (jobserver_semaphore_name);
137 /* Wait for either the jobserver semaphore to become signalled or one of our
138 * child processes to terminate.
140 int wait_for_semaphore_or_child_process()
142 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
143 DWORD dwHandleCount = 1;
144 DWORD dwEvent;
145 int i;
147 /* Add jobserver semaphore to first slot. */
148 handles[0] = jobserver_semaphore;
150 /* Build array of handles to wait for */
151 for (i = 0; i < proc_index; i++)
153 /* Don't wait on child processes that have already finished */
154 if (fake_exits_pending && proc_array[i]->exit_code)
155 continue;
157 handles[dwHandleCount++] = (HANDLE) proc_array[i]->pid;
160 dwEvent = WaitForMultipleObjects(
161 dwHandleCount, // number of objects in array
162 handles, // array of objects
163 FALSE, // wait for any object
164 INFINITE); // wait until object is signalled
166 switch(dwEvent)
168 case WAIT_FAILED:
169 return -1;
171 case WAIT_OBJECT_0:
172 /* Indicate that the semaphore was signalled */
173 return 1;
175 default:
176 /* Assume that one or more of the child processes terminated. */
177 return 0;
182 * When a process has been waited for, adjust the wait state
183 * array so that we don't wait for it again
185 static void
186 process_adjust_wait_state(sub_process* pproc)
188 int i;
190 if (!proc_index)
191 return;
193 for (i = 0; i < proc_index; i++)
194 if (proc_array[i]->pid == pproc->pid)
195 break;
197 if (i < proc_index) {
198 proc_index--;
199 if (i != proc_index)
200 memmove(&proc_array[i], &proc_array[i+1],
201 (proc_index-i) * sizeof(sub_process*));
202 proc_array[proc_index] = NULL;
207 * Waits for any of the registered child processes to finish.
209 static sub_process *
210 process_wait_for_any_private(int block, DWORD* pdwWaitStatus)
212 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
213 DWORD retval, which;
214 int i;
216 if (!proc_index)
217 return NULL;
219 /* build array of handles to wait for */
220 for (i = 0; i < proc_index; i++) {
221 handles[i] = (HANDLE) proc_array[i]->pid;
223 if (fake_exits_pending && proc_array[i]->exit_code)
224 break;
227 /* wait for someone to exit */
228 if (!fake_exits_pending) {
229 retval = WaitForMultipleObjects(proc_index, handles, FALSE, (block ? INFINITE : 0));
230 which = retval - WAIT_OBJECT_0;
231 } else {
232 fake_exits_pending--;
233 retval = !WAIT_FAILED;
234 which = i;
237 /* If the pointer is not NULL, set the wait status result variable. */
238 if (pdwWaitStatus)
239 *pdwWaitStatus = retval;
241 /* return pointer to process */
242 if ((retval == WAIT_TIMEOUT) || (retval == WAIT_FAILED)) {
243 return NULL;
245 else {
246 sub_process* pproc = proc_array[which];
247 process_adjust_wait_state(pproc);
248 return pproc;
253 * Terminate a process.
255 BOOL
256 process_kill(HANDLE proc, int signal)
258 sub_process* pproc = (sub_process*) proc;
259 pproc->signal = signal;
260 return (TerminateProcess((HANDLE) pproc->pid, signal));
264 * Use this function to register processes you wish to wait for by
265 * calling process_file_io(NULL) or process_wait_any(). This must be done
266 * because it is possible for callers of this library to reuse the same
267 * handle for multiple processes launches :-(
269 void
270 process_register(HANDLE proc)
272 if (proc_index < MAXIMUM_WAIT_OBJECTS)
273 proc_array[proc_index++] = (sub_process *) proc;
277 * Return the number of processes that we are still waiting for.
280 process_used_slots(void)
282 return proc_index;
286 * Public function which works kind of like waitpid(). Wait for any
287 * of the children to die and return results. To call this function,
288 * you must do 1 of things:
290 * x = process_easy(...);
292 * or
294 * x = process_init_fd();
295 * process_register(x);
297 * or
299 * x = process_init();
300 * process_register(x);
302 * You must NOT then call process_pipe_io() because this function is
303 * not capable of handling automatic notification of any child
304 * death.
307 HANDLE
308 process_wait_for_any(int block, DWORD* pdwWaitStatus)
310 sub_process* pproc = process_wait_for_any_private(block, pdwWaitStatus);
312 if (!pproc)
313 return NULL;
314 else {
316 * Ouch! can't tell caller if this fails directly. Caller
317 * will have to use process_last_err()
319 (void) process_file_io(pproc);
320 return ((HANDLE) pproc);
324 long
325 process_signal(HANDLE proc)
327 if (proc == INVALID_HANDLE_VALUE) return 0;
328 return (((sub_process *)proc)->signal);
331 long
332 process_last_err(HANDLE proc)
334 if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
335 return (((sub_process *)proc)->last_err);
338 long
339 process_exit_code(HANDLE proc)
341 if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE;
342 return (((sub_process *)proc)->exit_code);
346 2006-02:
347 All the following functions are currently unused.
348 All of them would crash gmake if called with argument INVALID_HANDLE_VALUE.
349 Hence whoever wants to use one of this functions must invent and implement
350 a reasonable error handling for this function.
352 char *
353 process_outbuf(HANDLE proc)
355 return (((sub_process *)proc)->outp);
358 char *
359 process_errbuf(HANDLE proc)
361 return (((sub_process *)proc)->errp);
365 process_outcnt(HANDLE proc)
367 return (((sub_process *)proc)->outcnt);
371 process_errcnt(HANDLE proc)
373 return (((sub_process *)proc)->errcnt);
376 void
377 process_pipes(HANDLE proc, int pipes[3])
379 pipes[0] = ((sub_process *)proc)->sv_stdin[0];
380 pipes[1] = ((sub_process *)proc)->sv_stdout[0];
381 pipes[2] = ((sub_process *)proc)->sv_stderr[0];
382 return;
386 HANDLE
387 process_init()
389 sub_process *pproc;
391 * open file descriptors for attaching stdin/stdout/sterr
393 HANDLE stdin_pipes[2];
394 HANDLE stdout_pipes[2];
395 HANDLE stderr_pipes[2];
396 SECURITY_ATTRIBUTES inherit;
397 BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
399 pproc = malloc(sizeof(*pproc));
400 memset(pproc, 0, sizeof(*pproc));
402 /* We can't use NULL for lpSecurityDescriptor because that
403 uses the default security descriptor of the calling process.
404 Instead we use a security descriptor with no DACL. This
405 allows nonrestricted access to the associated objects. */
407 if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),
408 SECURITY_DESCRIPTOR_REVISION)) {
409 pproc->last_err = GetLastError();
410 pproc->lerrno = E_SCALL;
411 return((HANDLE)pproc);
414 inherit.nLength = sizeof(inherit);
415 inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);
416 inherit.bInheritHandle = TRUE;
418 // By convention, parent gets pipe[0], and child gets pipe[1]
419 // This means the READ side of stdin pipe goes into pipe[1]
420 // and the WRITE side of the stdout and stderr pipes go into pipe[1]
421 if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||
422 CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||
423 CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {
425 pproc->last_err = GetLastError();
426 pproc->lerrno = E_SCALL;
427 return((HANDLE)pproc);
431 // Mark the parent sides of the pipes as non-inheritable
433 if (SetHandleInformation(stdin_pipes[0],
434 HANDLE_FLAG_INHERIT, 0) == FALSE ||
435 SetHandleInformation(stdout_pipes[0],
436 HANDLE_FLAG_INHERIT, 0) == FALSE ||
437 SetHandleInformation(stderr_pipes[0],
438 HANDLE_FLAG_INHERIT, 0) == FALSE) {
440 pproc->last_err = GetLastError();
441 pproc->lerrno = E_SCALL;
442 return((HANDLE)pproc);
444 pproc->sv_stdin[0] = (intptr_t) stdin_pipes[0];
445 pproc->sv_stdin[1] = (intptr_t) stdin_pipes[1];
446 pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0];
447 pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1];
448 pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0];
449 pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1];
451 pproc->using_pipes = 1;
453 pproc->lerrno = 0;
455 return((HANDLE)pproc);
459 HANDLE
460 process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)
462 sub_process *pproc;
464 pproc = malloc(sizeof(*pproc));
465 memset(pproc, 0, sizeof(*pproc));
468 * Just pass the provided file handles to the 'child side' of the
469 * pipe, bypassing pipes altogether.
471 pproc->sv_stdin[1] = (intptr_t) stdinh;
472 pproc->sv_stdout[1] = (intptr_t) stdouth;
473 pproc->sv_stderr[1] = (intptr_t) stderrh;
475 pproc->last_err = pproc->lerrno = 0;
477 return((HANDLE)pproc);
481 static HANDLE
482 find_file(const char *exec_path, const char *path_var,
483 char *full_fname, DWORD full_len)
485 HANDLE exec_handle;
486 char *fname;
487 char *ext;
488 DWORD req_len;
489 int i;
490 static const char *extensions[] =
491 /* Should .com come before no-extension case? */
492 { ".exe", ".cmd", ".bat", "", ".com", NULL };
494 fname = xmalloc(strlen(exec_path) + 5);
495 strcpy(fname, exec_path);
496 ext = fname + strlen(fname);
498 for (i = 0; extensions[i]; i++) {
499 strcpy(ext, extensions[i]);
500 if (((req_len = SearchPath (path_var, fname, NULL, full_len,
501 full_fname, NULL)) > 0
502 /* For compatibility with previous code, which
503 used OpenFile, and with Windows operation in
504 general, also look in various default
505 locations, such as Windows directory and
506 Windows System directory. Warning: this also
507 searches PATH in the Make's environment, which
508 might not be what the Makefile wants, but it
509 seems to be OK as a fallback, after the
510 previous SearchPath failed to find on child's
511 PATH. */
512 || (req_len = SearchPath (NULL, fname, NULL, full_len,
513 full_fname, NULL)) > 0)
514 && req_len <= full_len
515 && (exec_handle =
516 CreateFile(full_fname,
517 GENERIC_READ,
518 FILE_SHARE_READ | FILE_SHARE_WRITE,
519 NULL,
520 OPEN_EXISTING,
521 FILE_ATTRIBUTE_NORMAL,
522 NULL)) != INVALID_HANDLE_VALUE) {
523 free(fname);
524 return(exec_handle);
528 free(fname);
529 return INVALID_HANDLE_VALUE;
534 * Description: Create the child process to be helped
536 * Returns: success <=> 0
538 * Notes/Dependencies:
540 long
541 process_begin(
542 HANDLE proc,
543 char **argv,
544 char **envp,
545 char *exec_path,
546 char *as_user)
548 sub_process *pproc = (sub_process *)proc;
549 char *shell_name = 0;
550 int file_not_found=0;
551 HANDLE exec_handle;
552 char exec_fname[MAX_PATH];
553 const char *path_var = NULL;
554 char **ep;
555 char buf[256];
556 DWORD bytes_returned;
557 DWORD flags;
558 char *command_line;
559 STARTUPINFO startInfo;
560 PROCESS_INFORMATION procInfo;
561 char *envblk=NULL;
564 * Shell script detection... if the exec_path starts with #! then
565 * we want to exec shell-script-name exec-path, not just exec-path
566 * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not
567 * hard-code the path to the shell or perl or whatever: Instead, we
568 * assume it's in the path somewhere (generally, the NT tools
569 * bin directory)
572 /* Use the Makefile's value of PATH to look for the program to
573 execute, because it could be different from Make's PATH
574 (e.g., if the target sets its own value. */
575 if (envp)
576 for (ep = envp; *ep; ep++) {
577 if (strncmp (*ep, "PATH=", 5) == 0
578 || strncmp (*ep, "Path=", 5) == 0) {
579 path_var = *ep + 5;
580 break;
583 exec_handle = find_file(exec_path, path_var,
584 exec_fname, sizeof(exec_fname));
587 * If we couldn't open the file, just assume that Windows will be
588 * somehow able to find and execute it.
590 if (exec_handle == INVALID_HANDLE_VALUE) {
591 file_not_found++;
593 else {
594 /* Attempt to read the first line of the file */
595 if (ReadFile( exec_handle,
596 buf, sizeof(buf) - 1, /* leave room for trailing NULL */
597 &bytes_returned, 0) == FALSE || bytes_returned < 2) {
599 pproc->last_err = GetLastError();
600 pproc->lerrno = E_IO;
601 CloseHandle(exec_handle);
602 return(-1);
604 if (buf[0] == '#' && buf[1] == '!') {
606 * This is a shell script... Change the command line from
607 * exec_path args to shell_name exec_path args
609 char *p;
611 /* Make sure buf is NULL terminated */
612 buf[bytes_returned] = 0;
614 * Depending on the file system type, etc. the first line
615 * of the shell script may end with newline or newline-carriage-return
616 * Whatever it ends with, cut it off.
618 p= strchr(buf, '\n');
619 if (p)
620 *p = 0;
621 p = strchr(buf, '\r');
622 if (p)
623 *p = 0;
626 * Find base name of shell
628 shell_name = strrchr( buf, '/');
629 if (shell_name) {
630 shell_name++;
631 } else {
632 shell_name = &buf[2];/* skipping "#!" */
636 CloseHandle(exec_handle);
639 flags = 0;
641 if (file_not_found)
642 command_line = make_command_line( shell_name, exec_path, argv);
643 else
644 command_line = make_command_line( shell_name, exec_fname, argv);
646 if ( command_line == NULL ) {
647 pproc->last_err = 0;
648 pproc->lerrno = E_NO_MEM;
649 return(-1);
652 if (envp) {
653 if (arr2envblk(envp, &envblk) ==FALSE) {
654 pproc->last_err = 0;
655 pproc->lerrno = E_NO_MEM;
656 free( command_line );
657 return(-1);
661 if ((shell_name) || (file_not_found)) {
662 exec_path = 0; /* Search for the program in %Path% */
663 } else {
664 exec_path = exec_fname;
668 * Set up inherited stdin, stdout, stderr for child
670 GetStartupInfo(&startInfo);
671 startInfo.dwFlags = STARTF_USESTDHANDLES;
672 startInfo.lpReserved = 0;
673 startInfo.cbReserved2 = 0;
674 startInfo.lpReserved2 = 0;
675 startInfo.lpTitle = shell_name ? shell_name : exec_path;
676 startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
677 startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
678 startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
680 if (as_user) {
681 if (envblk) free(envblk);
682 return -1;
683 } else {
684 DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n",
685 exec_path ? exec_path : "NULL",
686 command_line ? command_line : "NULL"));
687 if (CreateProcess(
688 exec_path,
689 command_line,
690 NULL,
691 0, /* default security attributes for thread */
692 TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */
693 flags,
694 envblk,
695 0, /* default starting directory */
696 &startInfo,
697 &procInfo) == FALSE) {
699 pproc->last_err = GetLastError();
700 pproc->lerrno = E_FORK;
701 fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n",
702 exec_path ? exec_path : "NULL", command_line);
703 if (envblk) free(envblk);
704 free( command_line );
705 return(-1);
709 pproc->pid = (pid_t)procInfo.hProcess;
710 /* Close the thread handle -- we'll just watch the process */
711 CloseHandle(procInfo.hThread);
713 /* Close the halves of the pipes we don't need */
714 CloseHandle((HANDLE)pproc->sv_stdin[1]);
715 CloseHandle((HANDLE)pproc->sv_stdout[1]);
716 CloseHandle((HANDLE)pproc->sv_stderr[1]);
717 pproc->sv_stdin[1] = 0;
718 pproc->sv_stdout[1] = 0;
719 pproc->sv_stderr[1] = 0;
721 free( command_line );
722 if (envblk) free(envblk);
723 pproc->lerrno=0;
724 return 0;
729 static DWORD
730 proc_stdin_thread(sub_process *pproc)
732 DWORD in_done;
733 for (;;) {
734 if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,
735 &in_done, NULL) == FALSE)
736 _endthreadex(0);
737 // This if should never be true for anonymous pipes, but gives
738 // us a chance to change I/O mechanisms later
739 if (in_done < pproc->incnt) {
740 pproc->incnt -= in_done;
741 pproc->inp += in_done;
742 } else {
743 _endthreadex(0);
746 return 0; // for compiler warnings only.. not reached
749 static DWORD
750 proc_stdout_thread(sub_process *pproc)
752 DWORD bufsize = 1024;
753 char c;
754 DWORD nread;
755 pproc->outp = malloc(bufsize);
756 if (pproc->outp == NULL)
757 _endthreadex(0);
758 pproc->outcnt = 0;
760 for (;;) {
761 if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL)
762 == FALSE) {
763 /* map_windows32_error_to_string(GetLastError());*/
764 _endthreadex(0);
766 if (nread == 0)
767 _endthreadex(0);
768 if (pproc->outcnt + nread > bufsize) {
769 bufsize += nread + 512;
770 pproc->outp = realloc(pproc->outp, bufsize);
771 if (pproc->outp == NULL) {
772 pproc->outcnt = 0;
773 _endthreadex(0);
776 pproc->outp[pproc->outcnt++] = c;
778 return 0;
781 static DWORD
782 proc_stderr_thread(sub_process *pproc)
784 DWORD bufsize = 1024;
785 char c;
786 DWORD nread;
787 pproc->errp = malloc(bufsize);
788 if (pproc->errp == NULL)
789 _endthreadex(0);
790 pproc->errcnt = 0;
792 for (;;) {
793 if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {
794 map_windows32_error_to_string(GetLastError());
795 _endthreadex(0);
797 if (nread == 0)
798 _endthreadex(0);
799 if (pproc->errcnt + nread > bufsize) {
800 bufsize += nread + 512;
801 pproc->errp = realloc(pproc->errp, bufsize);
802 if (pproc->errp == NULL) {
803 pproc->errcnt = 0;
804 _endthreadex(0);
807 pproc->errp[pproc->errcnt++] = c;
809 return 0;
814 * Purpose: collects output from child process and returns results
816 * Description:
818 * Returns:
820 * Notes/Dependencies:
822 long
823 process_pipe_io(
824 HANDLE proc,
825 char *stdin_data,
826 int stdin_data_len)
828 sub_process *pproc = (sub_process *)proc;
829 bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;
830 HANDLE childhand = (HANDLE) pproc->pid;
831 HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL;
832 unsigned int dwStdin, dwStdout, dwStderr;
833 HANDLE wait_list[4];
834 DWORD wait_count;
835 DWORD wait_return;
836 HANDLE ready_hand;
837 bool_t child_dead = FALSE;
838 BOOL GetExitCodeResult;
841 * Create stdin thread, if needed
843 pproc->inp = stdin_data;
844 pproc->incnt = stdin_data_len;
845 if (!pproc->inp) {
846 stdin_eof = TRUE;
847 CloseHandle((HANDLE)pproc->sv_stdin[0]);
848 pproc->sv_stdin[0] = 0;
849 } else {
850 tStdin = (HANDLE) _beginthreadex( 0, 1024,
851 (unsigned (__stdcall *) (void *))proc_stdin_thread,
852 pproc, 0, &dwStdin);
853 if (tStdin == 0) {
854 pproc->last_err = GetLastError();
855 pproc->lerrno = E_SCALL;
856 goto done;
861 * Assume child will produce stdout and stderr
863 tStdout = (HANDLE) _beginthreadex( 0, 1024,
864 (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,
865 &dwStdout);
866 tStderr = (HANDLE) _beginthreadex( 0, 1024,
867 (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,
868 &dwStderr);
870 if (tStdout == 0 || tStderr == 0) {
872 pproc->last_err = GetLastError();
873 pproc->lerrno = E_SCALL;
874 goto done;
879 * Wait for all I/O to finish and for the child process to exit
882 while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
883 wait_count = 0;
884 if (!stdin_eof) {
885 wait_list[wait_count++] = tStdin;
887 if (!stdout_eof) {
888 wait_list[wait_count++] = tStdout;
890 if (!stderr_eof) {
891 wait_list[wait_count++] = tStderr;
893 if (!child_dead) {
894 wait_list[wait_count++] = childhand;
897 wait_return = WaitForMultipleObjects(wait_count, wait_list,
898 FALSE, /* don't wait for all: one ready will do */
899 child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
900 one second to collect all remaining output */
902 if (wait_return == WAIT_FAILED) {
903 /* map_windows32_error_to_string(GetLastError());*/
904 pproc->last_err = GetLastError();
905 pproc->lerrno = E_SCALL;
906 goto done;
909 ready_hand = wait_list[wait_return - WAIT_OBJECT_0];
911 if (ready_hand == tStdin) {
912 CloseHandle((HANDLE)pproc->sv_stdin[0]);
913 pproc->sv_stdin[0] = 0;
914 CloseHandle(tStdin);
915 tStdin = 0;
916 stdin_eof = TRUE;
918 } else if (ready_hand == tStdout) {
920 CloseHandle((HANDLE)pproc->sv_stdout[0]);
921 pproc->sv_stdout[0] = 0;
922 CloseHandle(tStdout);
923 tStdout = 0;
924 stdout_eof = TRUE;
926 } else if (ready_hand == tStderr) {
928 CloseHandle((HANDLE)pproc->sv_stderr[0]);
929 pproc->sv_stderr[0] = 0;
930 CloseHandle(tStderr);
931 tStderr = 0;
932 stderr_eof = TRUE;
934 } else if (ready_hand == childhand) {
936 DWORD ierr;
937 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
938 if (ierr == CONTROL_C_EXIT) {
939 pproc->signal = SIGINT;
940 } else {
941 pproc->exit_code = ierr;
943 if (GetExitCodeResult == FALSE) {
944 pproc->last_err = GetLastError();
945 pproc->lerrno = E_SCALL;
946 goto done;
948 child_dead = TRUE;
950 } else {
952 /* ?? Got back a handle we didn't query ?? */
953 pproc->last_err = 0;
954 pproc->lerrno = E_FAIL;
955 goto done;
959 done:
960 if (tStdin != 0)
961 CloseHandle(tStdin);
962 if (tStdout != 0)
963 CloseHandle(tStdout);
964 if (tStderr != 0)
965 CloseHandle(tStderr);
967 if (pproc->lerrno)
968 return(-1);
969 else
970 return(0);
975 * Purpose: collects output from child process and returns results
977 * Description:
979 * Returns:
981 * Notes/Dependencies:
983 long
984 process_file_io(
985 HANDLE proc)
987 sub_process *pproc;
988 HANDLE childhand;
989 DWORD wait_return;
990 BOOL GetExitCodeResult;
991 DWORD ierr;
993 if (proc == NULL)
994 pproc = process_wait_for_any_private(1, 0);
995 else
996 pproc = (sub_process *)proc;
998 /* some sort of internal error */
999 if (!pproc)
1000 return -1;
1002 childhand = (HANDLE) pproc->pid;
1005 * This function is poorly named, and could also be used just to wait
1006 * for child death if you're doing your own pipe I/O. If that is
1007 * the case, close the pipe handles here.
1009 if (pproc->sv_stdin[0]) {
1010 CloseHandle((HANDLE)pproc->sv_stdin[0]);
1011 pproc->sv_stdin[0] = 0;
1013 if (pproc->sv_stdout[0]) {
1014 CloseHandle((HANDLE)pproc->sv_stdout[0]);
1015 pproc->sv_stdout[0] = 0;
1017 if (pproc->sv_stderr[0]) {
1018 CloseHandle((HANDLE)pproc->sv_stderr[0]);
1019 pproc->sv_stderr[0] = 0;
1023 * Wait for the child process to exit
1026 wait_return = WaitForSingleObject(childhand, INFINITE);
1028 if (wait_return != WAIT_OBJECT_0) {
1029 /* map_windows32_error_to_string(GetLastError());*/
1030 pproc->last_err = GetLastError();
1031 pproc->lerrno = E_SCALL;
1032 goto done2;
1035 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
1036 if (ierr == CONTROL_C_EXIT) {
1037 pproc->signal = SIGINT;
1038 } else {
1039 pproc->exit_code = ierr;
1041 if (GetExitCodeResult == FALSE) {
1042 pproc->last_err = GetLastError();
1043 pproc->lerrno = E_SCALL;
1046 done2:
1047 if (pproc->lerrno)
1048 return(-1);
1049 else
1050 return(0);
1055 * Description: Clean up any leftover handles, etc. It is up to the
1056 * caller to manage and free the input, ouput, and stderr buffers.
1058 void
1059 process_cleanup(
1060 HANDLE proc)
1062 sub_process *pproc = (sub_process *)proc;
1063 int i;
1065 if (pproc->using_pipes) {
1066 for (i= 0; i <= 1; i++) {
1067 if ((HANDLE)pproc->sv_stdin[i])
1068 CloseHandle((HANDLE)pproc->sv_stdin[i]);
1069 if ((HANDLE)pproc->sv_stdout[i])
1070 CloseHandle((HANDLE)pproc->sv_stdout[i]);
1071 if ((HANDLE)pproc->sv_stderr[i])
1072 CloseHandle((HANDLE)pproc->sv_stderr[i]);
1075 if ((HANDLE)pproc->pid)
1076 CloseHandle((HANDLE)pproc->pid);
1078 free(pproc);
1083 * Description:
1084 * Create a command line buffer to pass to CreateProcess
1086 * Returns: the buffer or NULL for failure
1087 * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ...
1088 * Otherwise: argv[0] argv[1] argv[2] ...
1090 * Notes/Dependencies:
1091 * CreateProcess does not take an argv, so this command creates a
1092 * command line for the executable.
1095 static char *
1096 make_command_line( char *shell_name, char *full_exec_path, char **argv)
1098 int argc = 0;
1099 char** argvi;
1100 int* enclose_in_quotes = NULL;
1101 int* enclose_in_quotes_i;
1102 unsigned int bytes_required = 0;
1103 char* command_line;
1104 char* command_line_i;
1105 int cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */
1106 int have_sh = 0; /* HAVE_CYGWIN_SHELL */
1108 #ifdef HAVE_CYGWIN_SHELL
1109 have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe"));
1110 cygwin_mode = 1;
1111 #endif
1113 if (shell_name && full_exec_path) {
1114 bytes_required
1115 = strlen(shell_name) + 1 + strlen(full_exec_path);
1117 * Skip argv[0] if any, when shell_name is given.
1119 if (*argv) argv++;
1121 * Add one for the intervening space.
1123 if (*argv) bytes_required++;
1126 argvi = argv;
1127 while (*(argvi++)) argc++;
1129 if (argc) {
1130 enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));
1132 if (!enclose_in_quotes) {
1133 return NULL;
1137 /* We have to make one pass through each argv[i] to see if we need
1138 * to enclose it in ", so we might as well figure out how much
1139 * memory we'll need on the same pass.
1142 argvi = argv;
1143 enclose_in_quotes_i = enclose_in_quotes;
1144 while(*argvi) {
1145 char* p = *argvi;
1146 unsigned int backslash_count = 0;
1149 * We have to enclose empty arguments in ".
1151 if (!(*p)) *enclose_in_quotes_i = 1;
1153 while(*p) {
1154 switch (*p) {
1155 case '\"':
1157 * We have to insert a backslash for each "
1158 * and each \ that precedes the ".
1160 bytes_required += (backslash_count + 1);
1161 backslash_count = 0;
1162 break;
1164 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1165 case '\\':
1166 backslash_count++;
1167 break;
1168 #endif
1170 * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
1171 * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
1172 * that argv in always equals argv out. This was removed. Say you have
1173 * such a program named glob.exe. You enter
1174 * glob '*'
1175 * at the sh command prompt. Obviously the intent is to make glob do the
1176 * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?',
1177 * then the command line that glob would see would be
1178 * glob "*"
1179 * and the _setargv in SETARGV.OBJ would _not_ expand the *.
1181 case ' ':
1182 case '\t':
1183 *enclose_in_quotes_i = 1;
1184 /* fall through */
1186 default:
1187 backslash_count = 0;
1188 break;
1192 * Add one for each character in argv[i].
1194 bytes_required++;
1196 p++;
1199 if (*enclose_in_quotes_i) {
1201 * Add one for each enclosing ",
1202 * and one for each \ that precedes the
1203 * closing ".
1205 bytes_required += (backslash_count + 2);
1209 * Add one for the intervening space.
1211 if (*(++argvi)) bytes_required++;
1212 enclose_in_quotes_i++;
1216 * Add one for the terminating NULL.
1218 bytes_required++;
1220 command_line = (char*) malloc(bytes_required);
1222 if (!command_line) {
1223 if (enclose_in_quotes) free(enclose_in_quotes);
1224 return NULL;
1227 command_line_i = command_line;
1229 if (shell_name && full_exec_path) {
1230 while(*shell_name) {
1231 *(command_line_i++) = *(shell_name++);
1234 *(command_line_i++) = ' ';
1236 while(*full_exec_path) {
1237 *(command_line_i++) = *(full_exec_path++);
1240 if (*argv) {
1241 *(command_line_i++) = ' ';
1245 argvi = argv;
1246 enclose_in_quotes_i = enclose_in_quotes;
1248 while(*argvi) {
1249 char* p = *argvi;
1250 unsigned int backslash_count = 0;
1252 if (*enclose_in_quotes_i) {
1253 *(command_line_i++) = '\"';
1256 while(*p) {
1257 if (*p == '\"') {
1258 if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */
1259 /* instead of a \", cygwin likes "" */
1260 *(command_line_i++) = '\"';
1261 } else {
1264 * We have to insert a backslash for the "
1265 * and each \ that precedes the ".
1267 backslash_count++;
1269 while(backslash_count) {
1270 *(command_line_i++) = '\\';
1271 backslash_count--;
1274 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1275 } else if (*p == '\\') {
1276 backslash_count++;
1277 } else {
1278 backslash_count = 0;
1279 #endif
1283 * Copy the character.
1285 *(command_line_i++) = *(p++);
1288 if (*enclose_in_quotes_i) {
1289 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1291 * Add one \ for each \ that precedes the
1292 * closing ".
1294 while(backslash_count--) {
1295 *(command_line_i++) = '\\';
1297 #endif
1298 *(command_line_i++) = '\"';
1302 * Append an intervening space.
1304 if (*(++argvi)) {
1305 *(command_line_i++) = ' ';
1308 enclose_in_quotes_i++;
1312 * Append the terminating NULL.
1314 *command_line_i = '\0';
1316 if (enclose_in_quotes) free(enclose_in_quotes);
1317 return command_line;
1321 * Description: Given an argv and optional envp, launch the process
1322 * using the default stdin, stdout, and stderr handles.
1323 * Also, register process so that process_wait_for_any_private()
1324 * can be used via process_file_io(NULL) or
1325 * process_wait_for_any().
1327 * Returns:
1329 * Notes/Dependencies:
1331 HANDLE
1332 process_easy(
1333 char **argv,
1334 char **envp)
1336 HANDLE hIn;
1337 HANDLE hOut;
1338 HANDLE hErr;
1339 HANDLE hProcess;
1341 if (proc_index >= MAXIMUM_WAIT_OBJECTS) {
1342 DB (DB_JOBS, ("process_easy: All process slots used up\n"));
1343 return INVALID_HANDLE_VALUE;
1345 if (DuplicateHandle(GetCurrentProcess(),
1346 GetStdHandle(STD_INPUT_HANDLE),
1347 GetCurrentProcess(),
1348 &hIn,
1350 TRUE,
1351 DUPLICATE_SAME_ACCESS) == FALSE) {
1352 fprintf(stderr,
1353 "process_easy: DuplicateHandle(In) failed (e=%ld)\n",
1354 GetLastError());
1355 return INVALID_HANDLE_VALUE;
1357 if (DuplicateHandle(GetCurrentProcess(),
1358 GetStdHandle(STD_OUTPUT_HANDLE),
1359 GetCurrentProcess(),
1360 &hOut,
1362 TRUE,
1363 DUPLICATE_SAME_ACCESS) == FALSE) {
1364 fprintf(stderr,
1365 "process_easy: DuplicateHandle(Out) failed (e=%ld)\n",
1366 GetLastError());
1367 return INVALID_HANDLE_VALUE;
1369 if (DuplicateHandle(GetCurrentProcess(),
1370 GetStdHandle(STD_ERROR_HANDLE),
1371 GetCurrentProcess(),
1372 &hErr,
1374 TRUE,
1375 DUPLICATE_SAME_ACCESS) == FALSE) {
1376 fprintf(stderr,
1377 "process_easy: DuplicateHandle(Err) failed (e=%ld)\n",
1378 GetLastError());
1379 return INVALID_HANDLE_VALUE;
1382 hProcess = process_init_fd(hIn, hOut, hErr);
1384 if (process_begin(hProcess, argv, envp, argv[0], NULL)) {
1385 fake_exits_pending++;
1386 /* process_begin() failed: make a note of that. */
1387 if (!((sub_process*) hProcess)->last_err)
1388 ((sub_process*) hProcess)->last_err = -1;
1389 ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);
1391 /* close up unused handles */
1392 CloseHandle(hIn);
1393 CloseHandle(hOut);
1394 CloseHandle(hErr);
1397 process_register(hProcess);
1399 return hProcess;