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