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