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