Imported Upstream version 3.82
[platform/upstream/make.git] / w32 / subproc / sub_proc.c
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.
5
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.
10
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.
14
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/>.  */
17
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>
29
30 #include "sub_proc.h"
31 #include "proc.h"
32 #include "w32err.h"
33 #include "debug.h"
34
35 static char *make_command_line(char *shell_name, char *exec_path, char **argv);
36 extern char *xmalloc (unsigned int);
37
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;
55
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;
60
61 /*
62  * When a process has been waited for, adjust the wait state
63  * array so that we don't wait for it again
64  */
65 static void
66 process_adjust_wait_state(sub_process* pproc)
67 {
68         int i;
69
70         if (!proc_index)
71                 return;
72
73         for (i = 0; i < proc_index; i++)
74                 if (proc_array[i]->pid == pproc->pid)
75                         break;
76
77         if (i < proc_index) {
78                 proc_index--;
79                 if (i != proc_index)
80                         memmove(&proc_array[i], &proc_array[i+1],
81                                 (proc_index-i) * sizeof(sub_process*));
82                 proc_array[proc_index] = NULL;
83         }
84 }
85
86 /*
87  * Waits for any of the registered child processes to finish.
88  */
89 static sub_process *
90 process_wait_for_any_private(void)
91 {
92         HANDLE handles[MAXIMUM_WAIT_OBJECTS];
93         DWORD retval, which;
94         int i;
95
96         if (!proc_index)
97                 return NULL;
98
99         /* build array of handles to wait for */
100         for (i = 0; i < proc_index; i++) {
101                 handles[i] = (HANDLE) proc_array[i]->pid;
102
103                 if (fake_exits_pending && proc_array[i]->exit_code)
104                         break;
105         }
106
107         /* wait for someone to exit */
108         if (!fake_exits_pending) {
109                 retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE);
110                 which = retval - WAIT_OBJECT_0;
111         } else {
112                 fake_exits_pending--;
113                 retval = !WAIT_FAILED;
114                 which = i;
115         }
116
117         /* return pointer to process */
118         if (retval != WAIT_FAILED) {
119                 sub_process* pproc = proc_array[which];
120                 process_adjust_wait_state(pproc);
121                 return pproc;
122         } else
123                 return NULL;
124 }
125
126 /*
127  * Terminate a process.
128  */
129 BOOL
130 process_kill(HANDLE proc, int signal)
131 {
132         sub_process* pproc = (sub_process*) proc;
133         pproc->signal = signal;
134         return (TerminateProcess((HANDLE) pproc->pid, signal));
135 }
136
137 /*
138  * Use this function to register processes you wish to wait for by
139  * calling process_file_io(NULL) or process_wait_any(). This must be done
140  * because it is possible for callers of this library to reuse the same
141  * handle for multiple processes launches :-(
142  */
143 void
144 process_register(HANDLE proc)
145 {
146         if (proc_index < MAXIMUM_WAIT_OBJECTS)
147                 proc_array[proc_index++] = (sub_process *) proc;
148 }
149
150 /*
151  * Return the number of processes that we are still waiting for.
152  */
153 int
154 process_used_slots(void)
155 {
156         return proc_index;
157 }
158
159 /*
160  * Public function which works kind of like waitpid(). Wait for any
161  * of the children to die and return results. To call this function,
162  * you must do 1 of things:
163  *
164  *      x = process_easy(...);
165  *
166  * or
167  *
168  *      x = process_init_fd();
169  *      process_register(x);
170  *
171  * or
172  *
173  *      x = process_init();
174  *      process_register(x);
175  *
176  * You must NOT then call process_pipe_io() because this function is
177  * not capable of handling automatic notification of any child
178  * death.
179  */
180
181 HANDLE
182 process_wait_for_any(void)
183 {
184         sub_process* pproc = process_wait_for_any_private();
185
186         if (!pproc)
187                 return NULL;
188         else {
189                 /*
190                  * Ouch! can't tell caller if this fails directly. Caller
191                  * will have to use process_last_err()
192                  */
193                 (void) process_file_io(pproc);
194                 return ((HANDLE) pproc);
195         }
196 }
197
198 long
199 process_signal(HANDLE proc)
200 {
201         if (proc == INVALID_HANDLE_VALUE) return 0;
202         return (((sub_process *)proc)->signal);
203 }
204
205 long
206 process_last_err(HANDLE proc)
207 {
208         if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
209         return (((sub_process *)proc)->last_err);
210 }
211
212 long
213 process_exit_code(HANDLE proc)
214 {
215         if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE;
216         return (((sub_process *)proc)->exit_code);
217 }
218
219 /*
220 2006-02:
221 All the following functions are currently unused.
222 All of them would crash gmake if called with argument INVALID_HANDLE_VALUE.
223 Hence whoever wants to use one of this functions must invent and implement
224 a reasonable error handling for this function.
225
226 char *
227 process_outbuf(HANDLE proc)
228 {
229         return (((sub_process *)proc)->outp);
230 }
231
232 char *
233 process_errbuf(HANDLE proc)
234 {
235         return (((sub_process *)proc)->errp);
236 }
237
238 int
239 process_outcnt(HANDLE proc)
240 {
241         return (((sub_process *)proc)->outcnt);
242 }
243
244 int
245 process_errcnt(HANDLE proc)
246 {
247         return (((sub_process *)proc)->errcnt);
248 }
249
250 void
251 process_pipes(HANDLE proc, int pipes[3])
252 {
253         pipes[0] = ((sub_process *)proc)->sv_stdin[0];
254         pipes[1] = ((sub_process *)proc)->sv_stdout[0];
255         pipes[2] = ((sub_process *)proc)->sv_stderr[0];
256         return;
257 }
258 */
259
260         HANDLE
261 process_init()
262 {
263         sub_process *pproc;
264         /*
265          * open file descriptors for attaching stdin/stdout/sterr
266          */
267         HANDLE stdin_pipes[2];
268         HANDLE stdout_pipes[2];
269         HANDLE stderr_pipes[2];
270         SECURITY_ATTRIBUTES inherit;
271         BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
272
273         pproc = malloc(sizeof(*pproc));
274         memset(pproc, 0, sizeof(*pproc));
275
276         /* We can't use NULL for lpSecurityDescriptor because that
277            uses the default security descriptor of the calling process.
278            Instead we use a security descriptor with no DACL.  This
279            allows nonrestricted access to the associated objects. */
280
281         if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),
282                                           SECURITY_DESCRIPTOR_REVISION)) {
283                 pproc->last_err = GetLastError();
284                 pproc->lerrno = E_SCALL;
285                 return((HANDLE)pproc);
286         }
287
288         inherit.nLength = sizeof(inherit);
289         inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);
290         inherit.bInheritHandle = TRUE;
291
292         // By convention, parent gets pipe[0], and child gets pipe[1]
293         // This means the READ side of stdin pipe goes into pipe[1]
294         // and the WRITE side of the stdout and stderr pipes go into pipe[1]
295         if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||
296         CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||
297         CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {
298
299                 pproc->last_err = GetLastError();
300                 pproc->lerrno = E_SCALL;
301                 return((HANDLE)pproc);
302         }
303
304         //
305         // Mark the parent sides of the pipes as non-inheritable
306         //
307         if (SetHandleInformation(stdin_pipes[0],
308                                 HANDLE_FLAG_INHERIT, 0) == FALSE ||
309                 SetHandleInformation(stdout_pipes[0],
310                                 HANDLE_FLAG_INHERIT, 0) == FALSE ||
311                 SetHandleInformation(stderr_pipes[0],
312                                 HANDLE_FLAG_INHERIT, 0) == FALSE) {
313
314                 pproc->last_err = GetLastError();
315                 pproc->lerrno = E_SCALL;
316                 return((HANDLE)pproc);
317         }
318         pproc->sv_stdin[0]  = (intptr_t) stdin_pipes[0];
319         pproc->sv_stdin[1]  = (intptr_t) stdin_pipes[1];
320         pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0];
321         pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1];
322         pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0];
323         pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1];
324
325         pproc->using_pipes = 1;
326
327         pproc->lerrno = 0;
328
329         return((HANDLE)pproc);
330 }
331
332
333         HANDLE
334 process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)
335 {
336         sub_process *pproc;
337
338         pproc = malloc(sizeof(*pproc));
339         memset(pproc, 0, sizeof(*pproc));
340
341         /*
342          * Just pass the provided file handles to the 'child side' of the
343          * pipe, bypassing pipes altogether.
344          */
345         pproc->sv_stdin[1]  = (intptr_t) stdinh;
346         pproc->sv_stdout[1] = (intptr_t) stdouth;
347         pproc->sv_stderr[1] = (intptr_t) stderrh;
348
349         pproc->last_err = pproc->lerrno = 0;
350
351         return((HANDLE)pproc);
352 }
353
354
355 static HANDLE
356 find_file(const char *exec_path, const char *path_var,
357           char *full_fname, DWORD full_len)
358 {
359         HANDLE exec_handle;
360         char *fname;
361         char *ext;
362         DWORD req_len;
363         int i;
364         static const char *extensions[] =
365           /* Should .com come before no-extension case?  */
366           { ".exe", ".cmd", ".bat", "", ".com", NULL };
367
368         fname = xmalloc(strlen(exec_path) + 5);
369         strcpy(fname, exec_path);
370         ext = fname + strlen(fname);
371
372         for (i = 0; extensions[i]; i++) {
373                 strcpy(ext, extensions[i]);
374                 if (((req_len = SearchPath (path_var, fname, NULL, full_len,
375                                             full_fname, NULL)) > 0
376                      /* For compatibility with previous code, which
377                         used OpenFile, and with Windows operation in
378                         general, also look in various default
379                         locations, such as Windows directory and
380                         Windows System directory.  Warning: this also
381                         searches PATH in the Make's environment, which
382                         might not be what the Makefile wants, but it
383                         seems to be OK as a fallback, after the
384                         previous SearchPath failed to find on child's
385                         PATH.  */
386                      || (req_len = SearchPath (NULL, fname, NULL, full_len,
387                                                full_fname, NULL)) > 0)
388                     && req_len <= full_len
389                     && (exec_handle =
390                                 CreateFile(full_fname,
391                                            GENERIC_READ,
392                                            FILE_SHARE_READ | FILE_SHARE_WRITE,
393                                            NULL,
394                                            OPEN_EXISTING,
395                                            FILE_ATTRIBUTE_NORMAL,
396                                            NULL)) != INVALID_HANDLE_VALUE) {
397                         free(fname);
398                         return(exec_handle);
399                 }
400         }
401
402         free(fname);
403         return INVALID_HANDLE_VALUE;
404 }
405
406
407 /*
408  * Description:   Create the child process to be helped
409  *
410  * Returns: success <=> 0
411  *
412  * Notes/Dependencies:
413  */
414 long
415 process_begin(
416         HANDLE proc,
417         char **argv,
418         char **envp,
419         char *exec_path,
420         char *as_user)
421 {
422         sub_process *pproc = (sub_process *)proc;
423         char *shell_name = 0;
424         int file_not_found=0;
425         HANDLE exec_handle;
426         char exec_fname[MAX_PATH];
427         const char *path_var = NULL;
428         char **ep;
429         char buf[256];
430         DWORD bytes_returned;
431         DWORD flags;
432         char *command_line;
433         STARTUPINFO startInfo;
434         PROCESS_INFORMATION procInfo;
435         char *envblk=NULL;
436
437         /*
438          *  Shell script detection...  if the exec_path starts with #! then
439          *  we want to exec shell-script-name exec-path, not just exec-path
440          *  NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl.  We do not
441          *  hard-code the path to the shell or perl or whatever:  Instead, we
442          *  assume it's in the path somewhere (generally, the NT tools
443          *  bin directory)
444          */
445
446         /* Use the Makefile's value of PATH to look for the program to
447            execute, because it could be different from Make's PATH
448            (e.g., if the target sets its own value.  */
449         if (envp)
450                 for (ep = envp; *ep; ep++) {
451                         if (strncmp (*ep, "PATH=", 5) == 0
452                             || strncmp (*ep, "Path=", 5) == 0) {
453                                 path_var = *ep + 5;
454                                 break;
455                         }
456                 }
457         exec_handle = find_file(exec_path, path_var,
458                                 exec_fname, sizeof(exec_fname));
459
460         /*
461          * If we couldn't open the file, just assume that Windows will be
462          * somehow able to find and execute it.
463          */
464         if (exec_handle == INVALID_HANDLE_VALUE) {
465                 file_not_found++;
466         }
467         else {
468                 /* Attempt to read the first line of the file */
469                 if (ReadFile( exec_handle,
470                                 buf, sizeof(buf) - 1, /* leave room for trailing NULL */
471                                 &bytes_returned, 0) == FALSE || bytes_returned < 2) {
472
473                         pproc->last_err = GetLastError();
474                         pproc->lerrno = E_IO;
475                         CloseHandle(exec_handle);
476                         return(-1);
477                 }
478                 if (buf[0] == '#' && buf[1] == '!') {
479                         /*
480                          *  This is a shell script...  Change the command line from
481                          *      exec_path args to shell_name exec_path args
482                          */
483                         char *p;
484
485                         /*  Make sure buf is NULL terminated */
486                         buf[bytes_returned] = 0;
487                         /*
488                          * Depending on the file system type, etc. the first line
489                          * of the shell script may end with newline or newline-carriage-return
490                          * Whatever it ends with, cut it off.
491                          */
492                         p= strchr(buf, '\n');
493                         if (p)
494                                 *p = 0;
495                         p = strchr(buf, '\r');
496                         if (p)
497                                 *p = 0;
498
499                         /*
500                          *  Find base name of shell
501                          */
502                         shell_name = strrchr( buf, '/');
503                         if (shell_name) {
504                                 shell_name++;
505                         } else {
506                                 shell_name = &buf[2];/* skipping "#!" */
507                         }
508
509                 }
510                 CloseHandle(exec_handle);
511         }
512
513         flags = 0;
514
515         if (file_not_found)
516                 command_line = make_command_line( shell_name, exec_path, argv);
517         else
518                 command_line = make_command_line( shell_name, exec_fname, argv);
519
520         if ( command_line == NULL ) {
521                 pproc->last_err = 0;
522                 pproc->lerrno = E_NO_MEM;
523                 return(-1);
524         }
525
526         if (envp) {
527                 if (arr2envblk(envp, &envblk) ==FALSE) {
528                         pproc->last_err = 0;
529                         pproc->lerrno = E_NO_MEM;
530                         free( command_line );
531                         return(-1);
532                 }
533         }
534
535         if ((shell_name) || (file_not_found)) {
536                 exec_path = 0;  /* Search for the program in %Path% */
537         } else {
538                 exec_path = exec_fname;
539         }
540
541         /*
542          *  Set up inherited stdin, stdout, stderr for child
543          */
544         GetStartupInfo(&startInfo);
545         startInfo.dwFlags = STARTF_USESTDHANDLES;
546         startInfo.lpReserved = 0;
547         startInfo.cbReserved2 = 0;
548         startInfo.lpReserved2 = 0;
549         startInfo.lpTitle = shell_name ? shell_name : exec_path;
550         startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
551         startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
552         startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
553
554         if (as_user) {
555                 if (envblk) free(envblk);
556                 return -1;
557         } else {
558                 DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n",
559                         exec_path ? exec_path : "NULL",
560                         command_line ? command_line : "NULL"));
561                 if (CreateProcess(
562                         exec_path,
563                         command_line,
564                         NULL,
565                         0, /* default security attributes for thread */
566                         TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */
567                         flags,
568                         envblk,
569                         0, /* default starting directory */
570                         &startInfo,
571                         &procInfo) == FALSE) {
572
573                         pproc->last_err = GetLastError();
574                         pproc->lerrno = E_FORK;
575                         fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n",
576                                 exec_path ? exec_path : "NULL", command_line);
577                         if (envblk) free(envblk);
578                         free( command_line );
579                         return(-1);
580                 }
581         }
582
583         pproc->pid = (pid_t)procInfo.hProcess;
584         /* Close the thread handle -- we'll just watch the process */
585         CloseHandle(procInfo.hThread);
586
587         /* Close the halves of the pipes we don't need */
588         CloseHandle((HANDLE)pproc->sv_stdin[1]);
589         CloseHandle((HANDLE)pproc->sv_stdout[1]);
590         CloseHandle((HANDLE)pproc->sv_stderr[1]);
591         pproc->sv_stdin[1] = 0;
592         pproc->sv_stdout[1] = 0;
593         pproc->sv_stderr[1] = 0;
594
595         free( command_line );
596         if (envblk) free(envblk);
597         pproc->lerrno=0;
598         return 0;
599 }
600
601
602
603 static DWORD
604 proc_stdin_thread(sub_process *pproc)
605 {
606         DWORD in_done;
607         for (;;) {
608                 if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,
609                                          &in_done, NULL) == FALSE)
610                         _endthreadex(0);
611                 // This if should never be true for anonymous pipes, but gives
612                 // us a chance to change I/O mechanisms later
613                 if (in_done < pproc->incnt) {
614                         pproc->incnt -= in_done;
615                         pproc->inp += in_done;
616                 } else {
617                         _endthreadex(0);
618                 }
619         }
620         return 0; // for compiler warnings only.. not reached
621 }
622
623 static DWORD
624 proc_stdout_thread(sub_process *pproc)
625 {
626         DWORD bufsize = 1024;
627         char c;
628         DWORD nread;
629         pproc->outp = malloc(bufsize);
630         if (pproc->outp == NULL)
631                 _endthreadex(0);
632         pproc->outcnt = 0;
633
634         for (;;) {
635                 if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL)
636                                         == FALSE) {
637 /*                      map_windows32_error_to_string(GetLastError());*/
638                         _endthreadex(0);
639                 }
640                 if (nread == 0)
641                         _endthreadex(0);
642                 if (pproc->outcnt + nread > bufsize) {
643                         bufsize += nread + 512;
644                         pproc->outp = realloc(pproc->outp, bufsize);
645                         if (pproc->outp == NULL) {
646                                 pproc->outcnt = 0;
647                                 _endthreadex(0);
648                         }
649                 }
650                 pproc->outp[pproc->outcnt++] = c;
651         }
652         return 0;
653 }
654
655 static DWORD
656 proc_stderr_thread(sub_process *pproc)
657 {
658         DWORD bufsize = 1024;
659         char c;
660         DWORD nread;
661         pproc->errp = malloc(bufsize);
662         if (pproc->errp == NULL)
663                 _endthreadex(0);
664         pproc->errcnt = 0;
665
666         for (;;) {
667                 if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {
668                         map_windows32_error_to_string(GetLastError());
669                         _endthreadex(0);
670                 }
671                 if (nread == 0)
672                         _endthreadex(0);
673                 if (pproc->errcnt + nread > bufsize) {
674                         bufsize += nread + 512;
675                         pproc->errp = realloc(pproc->errp, bufsize);
676                         if (pproc->errp == NULL) {
677                                 pproc->errcnt = 0;
678                                 _endthreadex(0);
679                         }
680                 }
681                 pproc->errp[pproc->errcnt++] = c;
682         }
683         return 0;
684 }
685
686
687 /*
688  * Purpose: collects output from child process and returns results
689  *
690  * Description:
691  *
692  * Returns:
693  *
694  * Notes/Dependencies:
695  */
696         long
697 process_pipe_io(
698         HANDLE proc,
699         char *stdin_data,
700         int stdin_data_len)
701 {
702         sub_process *pproc = (sub_process *)proc;
703         bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;
704         HANDLE childhand = (HANDLE) pproc->pid;
705         HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL;
706         unsigned int dwStdin, dwStdout, dwStderr;
707         HANDLE wait_list[4];
708         DWORD wait_count;
709         DWORD wait_return;
710         HANDLE ready_hand;
711         bool_t child_dead = FALSE;
712         BOOL GetExitCodeResult;
713
714         /*
715          *  Create stdin thread, if needed
716          */
717         pproc->inp = stdin_data;
718         pproc->incnt = stdin_data_len;
719         if (!pproc->inp) {
720                 stdin_eof = TRUE;
721                 CloseHandle((HANDLE)pproc->sv_stdin[0]);
722                 pproc->sv_stdin[0] = 0;
723         } else {
724                 tStdin = (HANDLE) _beginthreadex( 0, 1024,
725                         (unsigned (__stdcall *) (void *))proc_stdin_thread,
726                                                   pproc, 0, &dwStdin);
727                 if (tStdin == 0) {
728                         pproc->last_err = GetLastError();
729                         pproc->lerrno = E_SCALL;
730                         goto done;
731                 }
732         }
733
734         /*
735          *   Assume child will produce stdout and stderr
736          */
737         tStdout = (HANDLE) _beginthreadex( 0, 1024,
738                 (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,
739                 &dwStdout);
740         tStderr = (HANDLE) _beginthreadex( 0, 1024,
741                 (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,
742                 &dwStderr);
743
744         if (tStdout == 0 || tStderr == 0) {
745
746                 pproc->last_err = GetLastError();
747                 pproc->lerrno = E_SCALL;
748                 goto done;
749         }
750
751
752         /*
753          *  Wait for all I/O to finish and for the child process to exit
754          */
755
756         while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
757                 wait_count = 0;
758                 if (!stdin_eof) {
759                         wait_list[wait_count++] = tStdin;
760                 }
761                 if (!stdout_eof) {
762                         wait_list[wait_count++] = tStdout;
763                 }
764                 if (!stderr_eof) {
765                         wait_list[wait_count++] = tStderr;
766                 }
767                 if (!child_dead) {
768                         wait_list[wait_count++] = childhand;
769                 }
770
771                 wait_return = WaitForMultipleObjects(wait_count, wait_list,
772                          FALSE, /* don't wait for all: one ready will do */
773                          child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
774                                 one second to collect all remaining output */
775
776                 if (wait_return == WAIT_FAILED) {
777 /*                      map_windows32_error_to_string(GetLastError());*/
778                         pproc->last_err = GetLastError();
779                         pproc->lerrno = E_SCALL;
780                         goto done;
781                 }
782
783                 ready_hand = wait_list[wait_return - WAIT_OBJECT_0];
784
785                 if (ready_hand == tStdin) {
786                         CloseHandle((HANDLE)pproc->sv_stdin[0]);
787                         pproc->sv_stdin[0] = 0;
788                         CloseHandle(tStdin);
789                         tStdin = 0;
790                         stdin_eof = TRUE;
791
792                 } else if (ready_hand == tStdout) {
793
794                         CloseHandle((HANDLE)pproc->sv_stdout[0]);
795                         pproc->sv_stdout[0] = 0;
796                         CloseHandle(tStdout);
797                         tStdout = 0;
798                         stdout_eof = TRUE;
799
800                 } else if (ready_hand == tStderr) {
801
802                         CloseHandle((HANDLE)pproc->sv_stderr[0]);
803                         pproc->sv_stderr[0] = 0;
804                         CloseHandle(tStderr);
805                         tStderr = 0;
806                         stderr_eof = TRUE;
807
808                 } else if (ready_hand == childhand) {
809
810                         DWORD ierr;
811                         GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
812                         if (ierr == CONTROL_C_EXIT) {
813                                 pproc->signal = SIGINT;
814                         } else {
815                                 pproc->exit_code = ierr;
816                         }
817                         if (GetExitCodeResult == FALSE) {
818                                 pproc->last_err = GetLastError();
819                                 pproc->lerrno = E_SCALL;
820                                 goto done;
821                         }
822                         child_dead = TRUE;
823
824                 } else {
825
826                         /* ?? Got back a handle we didn't query ?? */
827                         pproc->last_err = 0;
828                         pproc->lerrno = E_FAIL;
829                         goto done;
830                 }
831         }
832
833  done:
834         if (tStdin != 0)
835                 CloseHandle(tStdin);
836         if (tStdout != 0)
837                 CloseHandle(tStdout);
838         if (tStderr != 0)
839                 CloseHandle(tStderr);
840
841         if (pproc->lerrno)
842                 return(-1);
843         else
844                 return(0);
845
846 }
847
848 /*
849  * Purpose: collects output from child process and returns results
850  *
851  * Description:
852  *
853  * Returns:
854  *
855  * Notes/Dependencies:
856  */
857         long
858 process_file_io(
859         HANDLE proc)
860 {
861         sub_process *pproc;
862         HANDLE childhand;
863         DWORD wait_return;
864         BOOL GetExitCodeResult;
865         DWORD ierr;
866
867         if (proc == NULL)
868                 pproc = process_wait_for_any_private();
869         else
870                 pproc = (sub_process *)proc;
871
872         /* some sort of internal error */
873         if (!pproc)
874                 return -1;
875
876         childhand = (HANDLE) pproc->pid;
877
878         /*
879          * This function is poorly named, and could also be used just to wait
880          * for child death if you're doing your own pipe I/O.  If that is
881          * the case, close the pipe handles here.
882          */
883         if (pproc->sv_stdin[0]) {
884                 CloseHandle((HANDLE)pproc->sv_stdin[0]);
885                 pproc->sv_stdin[0] = 0;
886         }
887         if (pproc->sv_stdout[0]) {
888                 CloseHandle((HANDLE)pproc->sv_stdout[0]);
889                 pproc->sv_stdout[0] = 0;
890         }
891         if (pproc->sv_stderr[0]) {
892                 CloseHandle((HANDLE)pproc->sv_stderr[0]);
893                 pproc->sv_stderr[0] = 0;
894         }
895
896         /*
897          *  Wait for the child process to exit
898          */
899
900         wait_return = WaitForSingleObject(childhand, INFINITE);
901
902         if (wait_return != WAIT_OBJECT_0) {
903 /*              map_windows32_error_to_string(GetLastError());*/
904                 pproc->last_err = GetLastError();
905                 pproc->lerrno = E_SCALL;
906                 goto done2;
907         }
908
909         GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
910         if (ierr == CONTROL_C_EXIT) {
911                 pproc->signal = SIGINT;
912         } else {
913                 pproc->exit_code = ierr;
914         }
915         if (GetExitCodeResult == FALSE) {
916                 pproc->last_err = GetLastError();
917                 pproc->lerrno = E_SCALL;
918         }
919
920 done2:
921         if (pproc->lerrno)
922                 return(-1);
923         else
924                 return(0);
925
926 }
927
928 /*
929  * Description:  Clean up any leftover handles, etc.  It is up to the
930  * caller to manage and free the input, ouput, and stderr buffers.
931  */
932         void
933 process_cleanup(
934         HANDLE proc)
935 {
936         sub_process *pproc = (sub_process *)proc;
937         int i;
938
939         if (pproc->using_pipes) {
940                 for (i= 0; i <= 1; i++) {
941                         if ((HANDLE)pproc->sv_stdin[i])
942                                 CloseHandle((HANDLE)pproc->sv_stdin[i]);
943                         if ((HANDLE)pproc->sv_stdout[i])
944                                 CloseHandle((HANDLE)pproc->sv_stdout[i]);
945                         if ((HANDLE)pproc->sv_stderr[i])
946                                 CloseHandle((HANDLE)pproc->sv_stderr[i]);
947                 }
948         }
949         if ((HANDLE)pproc->pid)
950                 CloseHandle((HANDLE)pproc->pid);
951
952         free(pproc);
953 }
954
955
956 /*
957  * Description:
958  *       Create a command line buffer to pass to CreateProcess
959  *
960  * Returns:  the buffer or NULL for failure
961  *      Shell case:  sh_name a:/full/path/to/script argv[1] argv[2] ...
962  *  Otherwise:   argv[0] argv[1] argv[2] ...
963  *
964  * Notes/Dependencies:
965  *   CreateProcess does not take an argv, so this command creates a
966  *   command line for the executable.
967  */
968
969 static char *
970 make_command_line( char *shell_name, char *full_exec_path, char **argv)
971 {
972         int             argc = 0;
973         char**          argvi;
974         int*            enclose_in_quotes = NULL;
975         int*            enclose_in_quotes_i;
976         unsigned int    bytes_required = 0;
977         char*           command_line;
978         char*           command_line_i;
979         int  cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */
980         int have_sh = 0; /* HAVE_CYGWIN_SHELL */
981
982 #ifdef HAVE_CYGWIN_SHELL
983         have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe"));
984         cygwin_mode = 1;
985 #endif
986
987         if (shell_name && full_exec_path) {
988                 bytes_required
989                   = strlen(shell_name) + 1 + strlen(full_exec_path);
990                 /*
991                  * Skip argv[0] if any, when shell_name is given.
992                  */
993                 if (*argv) argv++;
994                 /*
995                  * Add one for the intervening space.
996                  */
997                 if (*argv) bytes_required++;
998         }
999
1000         argvi = argv;
1001         while (*(argvi++)) argc++;
1002
1003         if (argc) {
1004                 enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));
1005
1006                 if (!enclose_in_quotes) {
1007                         return NULL;
1008                 }
1009         }
1010
1011         /* We have to make one pass through each argv[i] to see if we need
1012          * to enclose it in ", so we might as well figure out how much
1013          * memory we'll need on the same pass.
1014          */
1015
1016         argvi = argv;
1017         enclose_in_quotes_i = enclose_in_quotes;
1018         while(*argvi) {
1019                 char* p = *argvi;
1020                 unsigned int backslash_count = 0;
1021
1022                 /*
1023                  * We have to enclose empty arguments in ".
1024                  */
1025                 if (!(*p)) *enclose_in_quotes_i = 1;
1026
1027                 while(*p) {
1028                         switch (*p) {
1029                         case '\"':
1030                                 /*
1031                                  * We have to insert a backslash for each "
1032                                  * and each \ that precedes the ".
1033                                  */
1034                                 bytes_required += (backslash_count + 1);
1035                                 backslash_count = 0;
1036                                 break;
1037
1038 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1039                         case '\\':
1040                                 backslash_count++;
1041                                 break;
1042 #endif
1043         /*
1044          * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
1045          * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
1046          * that argv in always equals argv out. This was removed.  Say you have
1047          * such a program named glob.exe.  You enter
1048          * glob '*'
1049          * at the sh command prompt.  Obviously the intent is to make glob do the
1050          * wildcarding instead of sh.  If we set *enclose_in_quotes_i for '*' or '?',
1051          * then the command line that glob would see would be
1052          * glob "*"
1053          * and the _setargv in SETARGV.OBJ would _not_ expand the *.
1054          */
1055                         case ' ':
1056                         case '\t':
1057                                 *enclose_in_quotes_i = 1;
1058                                 /* fall through */
1059
1060                         default:
1061                                 backslash_count = 0;
1062                                 break;
1063                         }
1064
1065                         /*
1066                          * Add one for each character in argv[i].
1067                          */
1068                         bytes_required++;
1069
1070                         p++;
1071                 }
1072
1073                 if (*enclose_in_quotes_i) {
1074                         /*
1075                          * Add one for each enclosing ",
1076                          * and one for each \ that precedes the
1077                          * closing ".
1078                          */
1079                         bytes_required += (backslash_count + 2);
1080                 }
1081
1082                 /*
1083                  * Add one for the intervening space.
1084                  */
1085                 if (*(++argvi)) bytes_required++;
1086                 enclose_in_quotes_i++;
1087         }
1088
1089         /*
1090          * Add one for the terminating NULL.
1091          */
1092         bytes_required++;
1093
1094         command_line = (char*) malloc(bytes_required);
1095
1096         if (!command_line) {
1097                 if (enclose_in_quotes) free(enclose_in_quotes);
1098                 return NULL;
1099         }
1100
1101         command_line_i = command_line;
1102
1103         if (shell_name && full_exec_path) {
1104                 while(*shell_name) {
1105                         *(command_line_i++) = *(shell_name++);
1106                 }
1107
1108                 *(command_line_i++) = ' ';
1109
1110                 while(*full_exec_path) {
1111                         *(command_line_i++) = *(full_exec_path++);
1112                 }
1113
1114                 if (*argv) {
1115                         *(command_line_i++) = ' ';
1116                 }
1117         }
1118
1119         argvi = argv;
1120         enclose_in_quotes_i = enclose_in_quotes;
1121
1122         while(*argvi) {
1123                 char* p = *argvi;
1124                 unsigned int backslash_count = 0;
1125
1126                 if (*enclose_in_quotes_i) {
1127                         *(command_line_i++) = '\"';
1128                 }
1129
1130                 while(*p) {
1131                         if (*p == '\"') {
1132                                 if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */
1133                                         /* instead of a \", cygwin likes "" */
1134                                         *(command_line_i++) = '\"';
1135                                 } else {
1136
1137                                 /*
1138                                  * We have to insert a backslash for the "
1139                                  * and each \ that precedes the ".
1140                                  */
1141                                 backslash_count++;
1142
1143                                 while(backslash_count) {
1144                                         *(command_line_i++) = '\\';
1145                                         backslash_count--;
1146                                 };
1147                                 }
1148 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1149                         } else if (*p == '\\') {
1150                                 backslash_count++;
1151                         } else {
1152                                 backslash_count = 0;
1153 #endif
1154                         }
1155
1156                         /*
1157                          * Copy the character.
1158                          */
1159                         *(command_line_i++) = *(p++);
1160                 }
1161
1162                 if (*enclose_in_quotes_i) {
1163 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1164                         /*
1165                          * Add one \ for each \ that precedes the
1166                          * closing ".
1167                          */
1168                         while(backslash_count--) {
1169                                 *(command_line_i++) = '\\';
1170                         };
1171 #endif
1172                         *(command_line_i++) = '\"';
1173                 }
1174
1175                 /*
1176                  * Append an intervening space.
1177                  */
1178                 if (*(++argvi)) {
1179                         *(command_line_i++) = ' ';
1180                 }
1181
1182                 enclose_in_quotes_i++;
1183         }
1184
1185         /*
1186          * Append the terminating NULL.
1187          */
1188         *command_line_i = '\0';
1189
1190         if (enclose_in_quotes) free(enclose_in_quotes);
1191         return command_line;
1192 }
1193
1194 /*
1195  * Description: Given an argv and optional envp, launch the process
1196  *              using the default stdin, stdout, and stderr handles.
1197  *              Also, register process so that process_wait_for_any_private()
1198  *              can be used via process_file_io(NULL) or
1199  *              process_wait_for_any().
1200  *
1201  * Returns:
1202  *
1203  * Notes/Dependencies:
1204  */
1205 HANDLE
1206 process_easy(
1207         char **argv,
1208         char **envp)
1209 {
1210   HANDLE hIn;
1211   HANDLE hOut;
1212   HANDLE hErr;
1213   HANDLE hProcess;
1214
1215   if (proc_index >= MAXIMUM_WAIT_OBJECTS) {
1216         DB (DB_JOBS, ("process_easy: All process slots used up\n"));
1217         return INVALID_HANDLE_VALUE;
1218   }
1219   if (DuplicateHandle(GetCurrentProcess(),
1220                       GetStdHandle(STD_INPUT_HANDLE),
1221                       GetCurrentProcess(),
1222                       &hIn,
1223                       0,
1224                       TRUE,
1225                       DUPLICATE_SAME_ACCESS) == FALSE) {
1226     fprintf(stderr,
1227             "process_easy: DuplicateHandle(In) failed (e=%ld)\n",
1228             GetLastError());
1229     return INVALID_HANDLE_VALUE;
1230   }
1231   if (DuplicateHandle(GetCurrentProcess(),
1232                       GetStdHandle(STD_OUTPUT_HANDLE),
1233                       GetCurrentProcess(),
1234                       &hOut,
1235                       0,
1236                       TRUE,
1237                       DUPLICATE_SAME_ACCESS) == FALSE) {
1238     fprintf(stderr,
1239            "process_easy: DuplicateHandle(Out) failed (e=%ld)\n",
1240            GetLastError());
1241     return INVALID_HANDLE_VALUE;
1242   }
1243   if (DuplicateHandle(GetCurrentProcess(),
1244                       GetStdHandle(STD_ERROR_HANDLE),
1245                       GetCurrentProcess(),
1246                       &hErr,
1247                       0,
1248                       TRUE,
1249                       DUPLICATE_SAME_ACCESS) == FALSE) {
1250     fprintf(stderr,
1251             "process_easy: DuplicateHandle(Err) failed (e=%ld)\n",
1252             GetLastError());
1253     return INVALID_HANDLE_VALUE;
1254   }
1255
1256   hProcess = process_init_fd(hIn, hOut, hErr);
1257
1258   if (process_begin(hProcess, argv, envp, argv[0], NULL)) {
1259     fake_exits_pending++;
1260     /* process_begin() failed: make a note of that.  */
1261     if (!((sub_process*) hProcess)->last_err)
1262       ((sub_process*) hProcess)->last_err = -1;
1263     ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);
1264
1265     /* close up unused handles */
1266     CloseHandle(hIn);
1267     CloseHandle(hOut);
1268     CloseHandle(hErr);
1269   }
1270
1271   process_register(hProcess);
1272
1273   return hProcess;
1274 }