# Patch created by Maciek
# Date: Wed Jun  2 17:40:17 WAST 2004
# Repository: pnet
# Comments:
# Updated patch addressing the issue of process spawning and output->pipe
# redirection on MinGW. At the last minute I've decided to leave the Cygwin
# part as it was before, this slightly adds to redundancy but doesn't make
# the output any larger.
# 
# Please note that this is not a complete MinGW port; there are still issues
# left to be resolved, e.g. CPP, possibly threading support.
#### End of Preamble ####

#### Patch data follows ####
Index: ChangeLog
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/ChangeLog,v
retrieving revision 1.2985
diff -c -r1.2985 ChangeLog
*** ChangeLog	2 Jun 2004 08:01:01 -0000	1.2985
--- ChangeLog	2 Jun 2004 09:41:02 -0000
***************
*** 1,3 ****
--- 1,22 ----
+ 2004-06-02  Maciek Plewa  <maciek@mil-sim.net>
+ 
+ 	* support/spawn.c: implemented process spawning and pipe redirection
+ 	support for Windows native (MinGW) - ILSpawnProcessWithPipe(),
+ 	ILSpawnProcess() and ILSpawnProcessWaitForExit(). Added utility
+ 	functions MakeOptionFile(), TranslateArguments(), CheckNT(),
+ 	WinError().
+ 
+ 	* support/cmdline.c, include/il_utils.h - added utility functions
+ 	ILCmdLineCopy and ILCmdLineToString. Modified the behaviour of
+ 	ILCmdLineExpand() to delete response files on Windows native.
+ 
+ 	* support/strings.c, include/il_system.h - added string quoting
+ 	utility	functions ILStrQCat() and ILStrQCpy().
+ 
+ 	* cscc/common/cc_main.c - updated SpawnOnPipe and ClosePipe to use
+ 	the IlSupport library (see above), renamed LoadLibrary() to
+ 	LoadLibraryCodeGen() to avoid conflicts with Windows API.
+ 
  2004-06-02  Thong Nguyen  <tum@veridicus.com>
  
  	* support/hb_gc.c: Changed GCNotifyFinalize to not wait for
Index: cscc/common/cc_main.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/cscc/common/cc_main.c,v
retrieving revision 1.33
diff -c -r1.33 cc_main.c
*** cscc/common/cc_main.c	14 Mar 2004 02:54:45 -0000	1.33
--- cscc/common/cc_main.c	2 Jun 2004 09:42:17 -0000
***************
*** 20,25 ****
--- 20,27 ----
  
  #include "cc_main.h"
  #include "cc_preproc.h"
+ #include "il_utils.h"
+ 
  #ifdef HAVE_SYS_TYPES_H
  	#include <sys/types.h>
  #endif
***************
*** 367,373 ****
   * Load the contents of a library into the code generator's context.
   * Returns zero if the library load failed.
   */
! static int LoadLibrary(const char *name, int nostdlib_flag, int later_load)
  {
  	int len;
  	int index;
--- 369,375 ----
   * Load the contents of a library into the code generator's context.
   * Returns zero if the library load failed.
   */
! static int LoadLibraryCodeGen(const char *name, int nostdlib_flag, int later_load)
  {
  	int len;
  	int index;
***************
*** 551,557 ****
  		{
  			name = "mscorlib";
  		}
! 		if(!LoadLibrary(name, 0, 0))
  		{
  			return 1;
  		}
--- 553,559 ----
  		{
  			name = "mscorlib";
  		}
! 		if(!LoadLibraryCodeGen(name, 0, 0))
  		{
  			return 1;
  		}
***************
*** 567,573 ****
  	/* Load all of the other libraries, in reverse order */
  	for(library = num_libraries - 1; library >= 0; --library)
  	{
! 		if(!LoadLibrary(libraries[library], nostdlib_flag, 0))
  		{
  			return 1;
  		}
--- 569,575 ----
  	/* Load all of the other libraries, in reverse order */
  	for(library = num_libraries - 1; library >= 0; --library)
  	{
! 		if(!LoadLibraryCodeGen(libraries[library], nostdlib_flag, 0))
  		{
  			return 1;
  		}
***************
*** 722,730 ****
   */
  static FILE *SpawnOnPipe(char **argv, int *pid)
  {
! #if defined(HAVE_FORK) && defined(HAVE_EXECV) && (defined(HAVE_WAITPID) || defined(HAVE_WAIT))
! 	int pipefds[2];
! 	FILE *file;
  
  	/* Report the command line if verbose mode is enabled */
  	if(verbose_mode == VERBOSE_CMDLINES)
--- 724,731 ----
   */
  static FILE *SpawnOnPipe(char **argv, int *pid)
  {
! 	FILE *file = 0;
! 	int tpid = 0;
  
  	/* Report the command line if verbose mode is enabled */
  	if(verbose_mode == VERBOSE_CMDLINES)
***************
*** 741,808 ****
  		putc('\n', stderr);
  	}
  
! 	/* Create a pipe to use to communicate with the child */
! 	if(pipe(pipefds) < 0)
! 	{
! 		perror("pipe");
! 		return 0;
! 	}
  
! 	/* Fork and create the child process */
! 	*pid = fork();
! 	if(*pid < 0)
! 	{
! 		/* We weren't able to fork the process */
! 		perror("fork");
! 		return 0;
! 	}
! 	else if(*pid == 0)
  	{
! 		/* We are in the child */
! 		dup2(pipefds[1], 1);
! 		close(pipefds[0]);
! 		close(pipefds[1]);
! 		execvp(argv[0], argv);
! 		perror("execvp");
! 		exit(1);
! 	}
! 	else
! 	{
! 		/* We are in the parent */
! 		close(pipefds[1]);
! 		file = fdopen(pipefds[0], "r");
! 		if(!file)
! 		{
! 			perror("fdopen");
! 		}
  		return file;
  	}
! 
! #else
! 	fputs("Don't know how to spawn child processes on this system\n", stderr);
! 	return 0;
! #endif
  }
  
  /*
!  * Close the pipe that was created by "SpawnOnPipe".
   */
! static int ClosePipe(FILE *file, int pid)
  {
! #if defined(HAVE_FORK) && defined(HAVE_EXECV) && (defined(HAVE_WAITPID) || defined(HAVE_WAIT))
! 	int status = 1;
  	fclose(file);
! #ifdef HAVE_WAITPID
! 	waitpid(pid, &status, 0);
! #else
! 	{
! 		int result;
! 		while((result = wait(&status)) != pid && result != -1)
! 		{
! 			/* Some other child fell: not the one we are interested in */
! 		}
! 	}
! #endif
  	if(WIFEXITED(status))
  	{
  		return (WEXITSTATUS(status) == 0);
--- 742,769 ----
  		putc('\n', stderr);
  	}
  
! 	tpid = ILSpawnProcessWithPipe(argv, (void **)&file);
  
! 	if ((file) && (tpid))
  	{
! 		*pid = tpid;
  		return file;
  	}
! 	else
! 		return 0;
  }
  
  /*
!  * Close the pipe that was created by "ILSpawnProcessWithPipe".
   */
! static int ClosePipe(FILE *file, int pid, char *argv[])
  {
! 	int status = 0;
! 
  	fclose(file);
! 
! 	status = ILSpawnProcessWaitForExit(pid, argv);
! 
  	if(WIFEXITED(status))
  	{
  		return (WEXITSTATUS(status) == 0);
***************
*** 811,819 ****
  	{
  		return 0;
  	}
- #else
- 	return 0;
- #endif
  }
  
  /*
--- 772,777 ----
***************
*** 1033,1039 ****
  		if(preprocess_flag)
  		{
  			CCHaveErrors |= Preprocess();
! 			if(!ClosePipe(file, pid))
  			{
  				CCHaveErrors |= 1;
  			}
--- 991,997 ----
  		if(preprocess_flag)
  		{
  			CCHaveErrors |= Preprocess();
! 			if(!ClosePipe(file, pid, argv))
  			{
  				CCHaveErrors |= 1;
  			}
***************
*** 1071,1077 ****
  	}
  	else if(fileIsPipe)
  	{
! 		if(!ClosePipe(file, pid))
  		{
  			CCHaveErrors |= 1;
  		}
--- 1029,1035 ----
  	}
  	else if(fileIsPipe)
  	{
! 		if(!ClosePipe(file, pid, argv))
  		{
  			CCHaveErrors |= 1;
  		}
***************
*** 1320,1326 ****
  
  int CCLoadLibrary(const char *name)
  {
! 	return LoadLibrary(name, nostdlib_flag, 1);
  }
  
  /*
--- 1278,1284 ----
  
  int CCLoadLibrary(const char *name)
  {
! 	return LoadLibraryCodeGen(name, nostdlib_flag, 1);
  }
  
  /*
Index: include/il_system.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/include/il_system.h,v
retrieving revision 1.19
diff -c -r1.19 il_system.h
*** include/il_system.h	19 Sep 2003 02:12:44 -0000	1.19
--- include/il_system.h	2 Jun 2004 09:43:37 -0000
***************
*** 100,107 ****
--- 100,112 ----
  #endif
  
  /* String routines */
+ void *ILStrQCat(char *dest, const char *src);
+ void *ILStrQCpy(char *dest, const char *src);
+ 
  int ILStrICmp(const char *str1, const char *str2);
  int ILStrNICmp(const char *str1, const char *str2, int len);
+ 
+ int ILStrArrayLength(char **argv, int max);
  
  /* Memory mapped files */
  int ILMapFileToMemory(int fd, unsigned long start, unsigned long end,
Index: include/il_utils.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/include/il_utils.h,v
retrieving revision 1.25
diff -c -r1.25 il_utils.h
*** include/il_utils.h	3 Nov 2003 05:18:21 -0000	1.25
--- include/il_utils.h	2 Jun 2004 09:44:53 -0000
***************
*** 339,344 ****
--- 339,362 ----
  } ILCmdLineOption;
  
  /*
+  * Converts the given argument array to a string
+  */
+ char *ILCmdLineToString(char **argv, int quote);
+ 
+ 
+ /*
+  * Copies argument array argv to dest
+  */
+ int ILCmdLineCopy(char ***dest, char **argv);
+ 
+ 
+ /*
+  * Add an argument to a list of command-line arguments.
+  */
+ void ILCmdLineAddArgument(char ***list, int *num, char *str);
+ 
+ 
+ /*
   * Get the next option from a command-line.
   */
  int ILCmdLineNextOption(int *argc, char ***argv, int *state,
Index: support/cmdline.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/cmdline.c,v
retrieving revision 1.12
diff -c -r1.12 cmdline.c
*** support/cmdline.c	15 May 2003 02:46:28 -0000	1.12
--- support/cmdline.c	2 Jun 2004 09:46:00 -0000
***************
*** 193,198 ****
--- 193,279 ----
  	}
  }
  
+ /*
+  * Copies argument array argv to dest
+  */
+ int ILCmdLineCopy(char ***dest, char **argv)
+ {
+ 	int argc = -1, i = 0;
+ 
+ 	if (argv != NULL)
+ 	{
+ 		while (argv[argc] != NULL)
+ 			argc++;
+ 
+ 		(*dest) = (char **)ILMalloc(argc * sizeof(char *));
+ 
+ 		if (*dest != NULL)
+ 		{
+ 			for (i = 0; i < argc; i++)
+ 				(*dest)[i] = argv[i];
+ 		}
+ 		else
+ 			argc = -1;
+ 	}
+ 
+ 	return argc;
+ }
+ 
+ 
+ /*
+  * Converts the given argument array to a string, with each
+  * argument separated by space character. This function is
+  * useful for systems that don't accept regular argument arrays.
+  *
+  * If parameter 'quote' is 1, each argument will be enclosed
+  * in double quotes (")
+  *
+  * The function returns a pointer to the string; it is
+  * programmer'sresponsibility to free the allocated memory.
+  */
+ char *ILCmdLineToString(char **argv, int quote)
+ {
+ 	char *cmd = 0;
+ 	int i = 0, length = 0;
+ 
+ 	/* Calculate the total length of all strings in the array,
+ 	including extra characters such as double quotes and spaces */
+ 	for (i = 0; argv[i]; i++) {
+ 		if (quote == 1)
+ 			length += 3;	/* two quotation marks and a space */
+ 		else
+ 			length++;
+ 
+ 		length += (int)strlen(argv[i]);
+ 	}
+ 
+ 	cmd = (char *)ILMalloc(length);
+ 
+ 	if (!cmd)
+ 		return NULL;
+ 
+ 	/* Copy the program path */
+ 	if (quote == 1)
+ 		ILStrQCpy(cmd, argv[0]);
+ 	else
+ 		strcpy(cmd, argv[0]);
+ 
+ 	/* Concatenate remaining arguments */
+ 	for(i = 1; argv[i]; i++) {
+ 		strcat(cmd, " ");
+ 
+ 		if (quote == 1)
+ 		{
+ 			ILStrQCat(cmd, argv[i]);
+ 		}
+ 		else
+ 			strcat(cmd, argv[i]);
+ 	}
+ 
+ 	return cmd;
+ }
+ 
+ 
  int ILCmdLineNextOption(int *argc, char ***argv, int *state,
  						const ILCmdLineOption *options, char **param)
  {
***************
*** 386,391 ****
--- 467,483 ----
  }
  
  /*
+  * Add an argument to a list of command-line arguments.
+  */
+ void ILCmdLineAddArgument(char ***list, int *num, char *str)
+ {
+ 	int max;
+ 	max = *num;
+ 
+ 	AddNewArg(num, list, &max, str);
+ }
+ 
+ /*
   * Do we need to expand wildcard specifications?
   */
  #ifdef	IL_WIN32_NATIVE
***************
*** 657,662 ****
--- 749,760 ----
  					AddNewArg(&newArgc, &newArgv, &maxArgc, temp);
  				}
  				fclose(file);
+ 
+ 				/* If this process is spawned asynchronously, the parent has no
+ 				 way to delete the response file */
+ 				#ifdef IL_WIN32_NATIVE
+ 					remove(filename);
+ 				#endif
  			}
  			else
  			{
Index: support/spawn.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/spawn.c,v
retrieving revision 1.9
diff -c -r1.9 spawn.c
*** support/spawn.c	15 May 2003 02:46:28 -0000	1.9
--- support/spawn.c	2 Jun 2004 09:47:04 -0000
***************
*** 21,30 ****
  #include "il_system.h"
  #include "il_utils.h"
  #include <stdio.h>
  #ifdef IL_WIN32_PLATFORM
  	#include <windows.h>
  	#include <process.h>
! #elif !defined(__palmos__)
  	#ifdef HAVE_SYS_TYPES_H
  		#include <sys/types.h>
  	#endif
--- 21,46 ----
  #include "il_system.h"
  #include "il_utils.h"
  #include <stdio.h>
+ 
+ #if !defined(IL_WIN32_PLATFORM) && defined(HAVE_FORK) && defined(HAVE_EXECV)
+  && (defined(HAVE_WAITPID) || defined(HAVE_WAIT))
+ 	#define UNIX_SPAWN
+ #endif
+ 
  #ifdef IL_WIN32_PLATFORM
  	#include <windows.h>
+ 	#include <stdlib.h>
  	#include <process.h>
! 	#include <errno.h>
! 	#include <io.h>
! 	#include <fcntl.h> 
! 
! 	#if !defined(_MSC_VER) && !defined(intptr_t)
! 		#define intptr_t LONG
! 	#endif
! 
! #elif !defined(__palmos__) 
! 
  	#ifdef HAVE_SYS_TYPES_H
  		#include <sys/types.h>
  	#endif
***************
*** 34,65 ****
  	#ifdef HAVE_SYS_WAIT_H
  		#include <sys/wait.h>
  	#endif
- 	#ifndef WEXITSTATUS
- 		#define	WEXITSTATUS(status)		((unsigned)(status) >> 8)
- 	#endif
- 	#ifndef WIFEXITED
- 		#define	WIFEXITED(status)		(((status) & 255) == 0)
- 	#endif
- 	#ifndef WTERMSIG
- 		#define	WTERMSIG(status)		(((unsigned)(status)) & 0x7F)
- 	#endif
- 	#ifndef WIFSIGNALLED
- 		#define	WIFSIGNALLED(status)	(((status) & 255) != 0)
- 	#endif
- 	#ifndef WCOREDUMP
- 		#define	WCOREDUMP(status)		(((status) & 0x80) != 0)
- 	#endif
  	#include <signal.h>
  #endif
  
  #ifdef	__cplusplus
  extern	"C" {
  #endif
  
! #ifdef IL_WIN32_PLATFORM
  
  /*
   * Use Windows-specific functions to spawn child processes.
   */
  int ILSpawnProcess(char *argv[])
  {
--- 50,493 ----
  	#ifdef HAVE_SYS_WAIT_H
  		#include <sys/wait.h>
  	#endif
  	#include <signal.h>
+ 
+ #endif
+ 
+ #ifndef WEXITSTATUS
+ 	#define	WEXITSTATUS(status)		((unsigned)(status) >> 8)
+ #endif
+ #ifndef WIFEXITED
+ 	#define	WIFEXITED(status)		(((status) & 255) == 0)
+ #endif
+ #ifndef WTERMSIG
+ 	#define	WTERMSIG(status)		(((unsigned)(status)) & 0x7F)
+ #endif
+ #ifndef WIFSIGNALLED
+ 	#define	WIFSIGNALLED(status)	(((status) & 255) != 0)
+ #endif
+ #ifndef WCOREDUMP
+ 	#define	WCOREDUMP(status)		(((status) & 0x80) != 0)
  #endif
  
  #ifdef	__cplusplus
  extern	"C" {
  #endif
  
! /* ILSpawnProcessWithPipe and ILSpawnProcessWaitForExit are for MinGW only */
! #if defined(IL_WIN32_NATIVE)
! 
! /* For a given argument arrary 'argv', determine whether it's necessary
!  * to use a response file - i.e. a file containing the list of arguments.
!  *
!  * Response files are required for long argument arrays, or argument 
!  * strings with white spaces.
!  *
!  * If a response file is to be used, MakeOptionFile returns the number
!  * of argument array elements (from element 0) that can be passed directly
!  * to a process. The remaining elements are written to a temporary file,
!  * with the filename being assigned to 'tempfile' - remember to remove
!  * the file as soon as argument list is not needed anymore, e.g. after
!  * a process was executed.
!  *
!  * The function returns 0 if a response file is not necessary, in this
!  * case you can safely pass the argument array to spawn/fork functions.
!  *
!  * If an error occurs, -1 is returned.
!  */
! static int MakeOptionFile(char **argv, char **tempfile)
! {
! 	int arg = 1, len = 0, useResponseFile = 0;
! 	int responsePosn;
! 	FILE *file;
! 
! 	/* Scan the command-line to see if it may be too big to
! 	   fit in the system's command-line buffer.  If so, we
! 	   must write the options to a temporary file instead */
! 	while(argv[arg] != 0)
! 	{
! 		if (strchr(argv[arg], ' ') != 0
! 			|| argv[arg][0] == '\0'
! 			|| argv[arg][0] == '@')
! 		{
! 			/* We must quote this argument: always put it in the option file,
! 			   so that the options don't get messed up by Microsoft's version
! 			   of "spawn*", which doesn't quote arguments with spaces */
! 			useResponseFile = 1;
! 			break;
! 		}
! 		else
! 		{
! 			/* This argument doesn't need quoting, but may cause overflow */
! 			len += (int)strlen(argv[arg]);
! 
! 			if(len >= 1024)
! 			{
! 				useResponseFile = 1;
! 				break;
! 			}
! 		}
! 
! 		++len;
! 		++arg;
! 	}
! 
! 	if(!arg && useResponseFile)
! 	{
! 		++arg;
! 	}
! 
! 	/* The command line doesn't need quoting */
! 	if (useResponseFile != 1)
! 		return 0;
! 
! 	/* Generate a temporary file name (path) */
! 	*tempfile = tempnam("c:\\windows\\temp", "CMD");
! 
! 	if (*tempfile == NULL)
! 	{
! 		return -1;
! 	}
! 
! 	if ((file = fopen(*tempfile, "w")) == NULL)
! 	{
! 		return -1;
! 	}
! 	
! 	responsePosn = arg;
! 
! 	while (argv[arg] != 0)
! 	{
! 		if(argv[arg][0] == '\0' || argv[arg][0] == '@' ||
! 		   strchr(argv[arg], ' ') != 0)
! 		{
! 			fputc('"', file);
! 			fputs(argv[arg], file);
! 			fputc('"', file);
! 		}
! 		else
! 		{
! 			fputs(argv[arg], file);
! 		}
! 
! 		putc('\n', file);
! 		++arg;
! 	}
! 
! 	fclose(file);
! 
! 	return responsePosn;
! }
! 
! 
! /* Translates a regular 'argv' argument array to its string equivalent,
!  * using an option file if necessary. */
! static int TranslateArguments(char **buffer, char **tempfile, char *argv[])
! {	
! 	int responsePosn = 0, arg = 0, cmdlen = 0;
! 	char *command = 0;
! 
! 	/* Check if we need to use an option file,
! 	responsePosn will be the number of first argv
! 	elements that can be passed to spawned process,
! 	the rest of elements will go in the option file */
! 	responsePosn = MakeOptionFile(argv, tempfile);
! 
! 	/* If some arguments have to be passed in the option file,
! 	the temporary file must exist */
! 	if (responsePosn > 1 && tempfile)
! 	{
! 		/* Calculate the total length of all arguments
! 		that will be passed on the command line, including
! 		4 double quote characters, spaces, one '@' and NULL.
! 		Only the program path and temporary file path are
! 		quoted. */
! 		cmdlen = ILStrArrayLength(argv, responsePosn);
! 		cmdlen += (int)strlen(*tempfile) + responsePosn + 2 + 6;
! 
! 		command = (char *)ILMalloc(cmdlen);
! 
! 		if (command)
! 		{
! 			/* Copy the program path, arguments and option file
! 			argument to the command line string */
! 			ILStrQCpy(command, argv[0]);
! 
! 			for(arg = 1; arg < responsePosn; ++arg)
! 			{
! 				strcat(command, " ");
! 				strcat(command, argv[arg]);
! 			}
! 
! 			strcat(command, " @");
! 			ILStrQCat(command, *tempfile);
! 		}
! 		else
! 		{
! 			remove(*tempfile);
! 			ILFree(*tempfile);
! 			return -1;
! 		}
! 	}
! 	/* We need to use the option file, but the file
! 	was not created */
! 	else if (responsePosn > 1 && !tempfile)
! 		return -1;
! 
! 	/* There's no need for the option file, dump the argument array
! 	to string */
! 	else if (!responsePosn)
! 	{
! 		/* Turn argv into a form acceptable to CreateProcess.  */
! 		command = ILCmdLineToString(argv, 1);
! 	}
! 
! 	*buffer = command;
! 
! 	return 1;
! }
! 
! /* perror for Windows - shows last Windows error message */
! static void WinError(const char *message)
! {
! 	LPVOID sysmsg;
! 
! 	FormatMessage(
! 		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
! 		NULL,
! 		GetLastError(),
! 		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
! 		(LPTSTR) &sysmsg,
! 		0,
! 		NULL
! 	);
! 
! 	fprintf(stderr, "%s: %s\n", message, (char *)sysmsg);
! 
! 	LocalFree(sysmsg);
! }
! 
! /* Checks if the operating system is Windows NT (NT/2000/XP/2003)
!    returns 1 if yes, or 0 if not */
! static int CheckNT()
! {
! 	OSVERSIONINFO osv;
! 	osv.dwOSVersionInfoSize = sizeof(osv);
! 	
! 	GetVersionEx(&osv);
! 
! 	if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT)
! 		return TRUE;
! 	else
! 		return FALSE;
! }
  
  /*
   * Use Windows-specific functions to spawn child processes.
+  *
+  * This function is for Windows native
+  */
+ int ILSpawnProcess(char *argv[])
+ {
+ 	int create, status = 0;
+ 	char *command = 0, *tempfile = 0;
+ 
+ 	STARTUPINFO si;
+     PROCESS_INFORMATION pi;
+ 
+ 	if (TranslateArguments(&command, &tempfile, argv) == -1)
+ 		return -1;
+ 
+ 	/* Allocate memory for structures and obtain existing startup information */
+ 	ZeroMemory(&si, sizeof(si));
+     ZeroMemory(&pi, sizeof(pi));
+ 	GetStartupInfo(&si);
+ 	si.cb = sizeof(si);
+ 
+  	/* Start the child process */
+ 	create = CreateProcess(
+ 		NULL,							/* The full path of app to launch */
+ 		command,						/* Command line parameters */
+ 		NULL,							/* Default process security attributes */
+ 		NULL,							/* Default thread security attributes */
+ 		TRUE,							/* Inherit handles from the parent */
+ 		GetPriorityClass((HANDLE)-1),	/* Calling process' priority */
+ 		NULL,							/* Use the same environment as the parent */
+ 		NULL,							/* Use app's directory as current */
+ 		&si,							/* Startup Information */
+ 		&pi);							/* Process information stored upon return */
+ 
+ 	if (command)
+ 	{
+ 		ILFree(command);
+ 	}
+ 
+ 	if (tempfile)
+ 	{
+ 		ILFree(tempfile);
+ 	}
+ 
+ 	if (create != 0)
+ 	{
+ 		/* warning: pointer truncation from HANDLE to int */
+ 		status = ILSpawnProcessWaitForExit((int)pi.hProcess, argv);
+ 	}
+ 	else
+ 	{
+ 		WinError("CreateProcess");
+ 		status = -1;
+ 	}
+ 
+ 	return status;
+ }
+ 
+ /* Wait for a process specified by pid to exit
+  * and return it's status code
+  *
+  * This function is for Windows (native)
+  */
+ int ILSpawnProcessWaitForExit(int pid, char *argv[])
+ {
+ 	int status = 0;
+ 
+ 	if (_cwait(&status, pid, _WAIT_CHILD) == pid)
+ 	{
+ 		return status;
+ 	}
+ 	else
+ 		return -1;
+ }
+ 
+ /* Spawns a new process with argument list 'argv'
+  * and redirects its standard output to 'stream'
+  *
+  * Returns a handle of the newly created process
+  *  
+  * This function is for Windows (native)
+  */
+ int ILSpawnProcessWithPipe(char *argv[], void **stream)
+ {
+ 	int fd, create;
+ 	char *command = 0, *tempfile = 0;
+ 
+ 	STARTUPINFO si;
+ 	SECURITY_ATTRIBUTES sa;
+ 	SECURITY_DESCRIPTOR sd;
+ 	PROCESS_INFORMATION pi;
+ 	HANDLE read_pipe, write_pipe;
+ 
+ 	if (TranslateArguments(&command, &tempfile, argv) == -1)
+ 		return -1;
+ 
+ 	/* Set the length of the security attribute structure and allow
+ 	   the handle to be inherited by child processes */
+ 	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ 	sa.bInheritHandle = TRUE;
+ 
+ 	/* Use a security descriptor for the new pipe on Windows NT-based systems */
+ 	if (CheckNT())
+ 	{
+ 		InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
+ 		SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
+ 		sa.lpSecurityDescriptor = &sd;
+ 	}
+ 	/* Pipe will use ACLs from default descriptor */
+ 	else
+ 		sa.lpSecurityDescriptor = NULL;
+ 
+ 	/* Create a new pipe with system's default buffer size */
+ 	if (!CreatePipe(&read_pipe, &write_pipe, &sa, 0))
+ 	{
+ 		WinError("CreatePipe");
+ 
+ 		CloseHandle(read_pipe);
+ 		CloseHandle(write_pipe);
+ 
+ 		return -1;
+ 	}
+ 
+ 	/* Allocate memory for structures and obtain existing startup information */
+ 	ZeroMemory(&si, sizeof(si));
+     ZeroMemory(&pi, sizeof(pi));
+ 	GetStartupInfo(&si);
+ 	si.cb = sizeof(si);
+ 
+ 	/* Sets the standard output handle for the process to the
+ 	   handle specified in hStdOutput */
+ 	si.dwFlags = STARTF_USESTDHANDLES;
+ 
+ 	si.hStdInput = (HANDLE)_get_osfhandle(0);
+ 	si.hStdOutput = write_pipe;
+ 	si.hStdError  = (HANDLE)_get_osfhandle(2);
+ 
+ 	_flushall();
+ 
+ 	/* Start the child process */
+ 	create = CreateProcess(
+ 		NULL,							/* The full path of app to launch */
+ 		command,						/* Command line parameters */
+ 		NULL,							/* Default process security attributes */
+ 		NULL,							/* Default thread security attributes */
+ 		TRUE,							/* Inherit handles from the parent */
+ 		GetPriorityClass((HANDLE)-1),	/* Calling process' priority */
+ 		NULL,							/* Use the same environment as the parent */
+ 		NULL,							/* Use app's directory as current */
+ 		&si,							/* Startup Information */
+ 		&pi);							/* Process information stored upon return */
+ 
+ 	if (command)
+ 		ILFree(command);
+ 
+ 	if (tempfile)
+ 	{
+ 		ILFree(tempfile);
+ 	}
+ 
+ 	if (!create)
+ 	{
+ 		WinError("CreateProcess");
+ 
+ 		CloseHandle(read_pipe);
+ 		CloseHandle(write_pipe);
+ 
+ 		return -1;
+ 	}
+ 
+ 	/* Associates a file descriptor with the stdout pipe */
+ 	fd = _open_osfhandle((intptr_t)read_pipe, _O_BINARY);
+ 
+ 	/* Close the handle that we're not going to use */
+ 	CloseHandle(write_pipe);
+ 	CloseHandle(pi.hThread);
+ 
+ 	if (!fd)
+ 	{
+ 		perror("_open_osfhandle");
+ 		return -1;
+ 	}
+ 
+ 	/* Open the pipe stream using its file descriptor */
+ 	*stream = fdopen(fd, "r");
+ 
+ 	if(!(*stream))
+ 	{
+ 		perror("fdopen");
+ 		close(fd);
+ 		return -1;
+ 	}
+ 
+ 	/* warning: pointer truncation from HANDLE to int */
+ 	return (int) pi.hProcess;
+ }
+ 
+ #elif defined(IL_WIN32_CYGWIN)
+ 
+ /*
+  * Use Windows-specific functions to spawn child processes.
+  * This function is for Cygwin
+  *
+  * TODO: Optimise the function by removing redundant code, use
+  * TranslateArguments() and MakeOptionFile()
   */
  int ILSpawnProcess(char *argv[])
  {
***************
*** 218,231 ****
  	return 1;
  }
  
! #else
! #if defined(HAVE_FORK) && defined(HAVE_EXECV) && (defined(HAVE_WAITPID) || defined(HAVE_WAIT))
  
  /*
   * Determine if a signal is important enough to be reported.
   * Simple exits like SIGINT, SIGTERM, etc are not considered
   * important as they are "normal" ways to abort a process.
   */
  static int ImportantSignal(unsigned sig)
  {
  #ifdef SIGSEGV
--- 646,688 ----
  	return 1;
  }
  
! #elif defined(UNIX_SPAWN)
! 
! /*
!  * Use Unix-specific functions to spawn child processes.
!  */
! int ILSpawnProcess(char *argv[])
! {
! 	int pid = fork();
! 	if(pid < 0)
! 	{
! 		/* Could not fork the child process */
! 		perror("fork");
! 		return -1;
! 	}
! 	else if(pid == 0)
! 	{
! 		/* We are in the child process */
! 		execvp(argv[0], argv);
! 		perror(argv[0]);
! 		exit(1);
! 		return -1;		/* Keep the compiler happy */
! 	}
! 	else
! 	{
! 		/* We are in the parent process */
! 		return ILSpawnProcessWaitForExit(pid, argv);
! 	}
! }
  
  /*
   * Determine if a signal is important enough to be reported.
   * Simple exits like SIGINT, SIGTERM, etc are not considered
   * important as they are "normal" ways to abort a process.
+  *
+  * This function is for UNIX and Cygwin
   */
+ 
  static int ImportantSignal(unsigned sig)
  {
  #ifdef SIGSEGV
***************
*** 249,281 ****
  	return 0;
  }
  
! /*
!  * Use Unix-specific functions to spawn child processes.
   */
- int ILSpawnProcess(char *argv[])
- {
- 	int pid = fork();
- 	if(pid < 0)
- 	{
- 		/* Could not fork the child process */
- 		perror("fork");
- 		return -1;
- 	}
- 	else if(pid == 0)
- 	{
- 		/* We are in the child process */
- 		execvp(argv[0], argv);
- 		perror(argv[0]);
- 		exit(1);
- 		return -1;		/* Keep the compiler happy */
- 	}
- 	else
- 	{
- 		/* We are in the parent process */
- 		return ILSpawnProcessWaitForExit(pid, argv);
- 	}
- }
- 
  int ILSpawnProcessWithPipe(char *argv[], void **stream)
  {
  	int pipefds[2];
--- 706,718 ----
  	return 0;
  }
  
! /* Spawns a new process with argument list 'argv'
!  * and redirects its standard output to 'stream'
!  *
!  * Returns a handle of the newly created process
!  *  
!  * This function is for UNIX and Cygwin
   */
  int ILSpawnProcessWithPipe(char *argv[], void **stream)
  {
  	int pipefds[2];
***************
*** 325,330 ****
--- 762,772 ----
  	}
  }
  
+ /* Wait for a process specified by pid to exit
+  * and return it's status code
+  *
+  * This function is for UNIX and Cygwin
+  */
  int ILSpawnProcessWaitForExit(int pid, char *argv[])
  {
  	int status = 1;
***************
*** 358,367 ****
  	}
  }
  
  #else
  
  /*
!  * We don't know how to spawn child processes on this system.
   */
  
  int ILSpawnProcess(char *argv[])
--- 800,811 ----
  	}
  }
  
+ 
  #else
  
  /*
!  * We don't support process spawning on systems other than Cygwin,
!  * native Windows or Unix (and compatible systems)
   */
  
  int ILSpawnProcess(char *argv[])
***************
*** 384,390 ****
  	return -1;
  }
  
- #endif
  #endif
  
  #ifdef	__cplusplus
--- 828,833 ----
Index: support/strings.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/strings.c,v
retrieving revision 1.2
diff -c -r1.2 strings.c
*** support/strings.c	8 Jul 2003 10:14:37 -0000	1.2
--- support/strings.c	2 Jun 2004 09:48:22 -0000
***************
*** 1,5 ****
  /*
!  * strings.c - System manipulation routines.
   *
   * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
   *
--- 1,5 ----
  /*
!  * strings.c - String manipulation routines.
   *
   * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
   *
***************
*** 23,28 ****
--- 23,82 ----
  #ifdef	__cplusplus
  extern	"C" {
  #endif
+ 
+ /* 
+  * Adds double quotes around 'src' and concatenates the resulting
+  * string to 'dest', returns a pointer to 'dest'
+  */
+ void *ILStrQCat(char *dest, const char *src)
+ {
+ 	if (src != NULL)
+ 	{
+ 		strcat(dest, "\"");
+ 		strcat(dest, src);
+ 		strcat(dest, "\"");
+ 
+ 		return dest;
+ 	}
+ 	else
+ 		return NULL;
+ }
+ 
+ /*
+  * Copies the string 'src' to 'dest' enclosing it with
+  * double quotes (") and returns a pointer to 'dest'
+  */
+ void *ILStrQCpy(char *dest, const char *src)
+ {
+ 	if (src != NULL)
+ 	{
+ 		strcpy(dest, "\"");
+ 		strcat(dest, src);
+ 		strcat(dest, "\"");
+ 
+ 		return dest;
+ 	}
+ 	else
+ 		return NULL;
+ }
+ 
+ /*
+  * Calculates the total length of all strings in an array.
+  * You can specify the maximum number of elements counted
+  * in the second argument 'max'
+  */
+ int ILStrArrayLength(char **argv, int max)
+ {
+ 	int length = 0, i = 0;
+ 
+ 	for(i = 0; argv[i]; i++) {
+ 		if ((max > 0) && i >= max)
+ 			break;
+ 		length += (int)strlen(argv[i]);
+ 	}
+ 
+ 	return length;
+ }
  
  /*
   * Note: this uses an English-style case comparison routine.
#### End of Patch data ####
