/**********************************************************************
 
	Copyright (C) 2003 
	Hirohisa MORI <joshua@nichibun.ac.jp>
	Tomohito Nakajima <nakajima@zeta.co.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/

#include	"machine/gb_windows.h"
#include	"stream.h"
#include	"init.h"
#include	"machine/stream.h"
#include	"memory_debug.h"

extern int s_task_flag;


void remove_command_line_ampersand(char *command_line){
	char *p;
	p = &command_line[strlen(command_line)-1];
	while(*p==' '||*p=='\t'){
		--p;
	}
	if(*p=='&'){
		*p = '\0';
	}
}

int
launch_proc_stdio(
	STREAM ** st_in,
	STREAM ** st_out,
	STREAM ** st_err,
	char * str)
{
	HANDLE h_in, h_out, h_err;

    STARTUPINFO  si;
    PROCESS_INFORMATION  pi;
    SECURITY_ATTRIBUTES sa;
	BOOL pass_handle;
	HANDLE std_in[2], std_out[2], std_err[2];
	char *command_line;

	int success = 0;
	
	if((str == NULL)||str[0]=='\0'){
		er_panic("launch_proc_stdio: invalid shell command");
	}
	/* printf("launch_proc_stdio str=%s\n", str); */
	command_line = d_alloc(strlen(str)+1);
	strcpy(command_line, str);
	remove_command_line_ampersand(command_line);
	
	memset(&sa, 0, sizeof(sa));
	sa.nLength = sizeof(sa);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;
	
	memset(&si, 0, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	
	if(	st_in && st_out && st_err){
		pass_handle=TRUE;
	}
	else{
		pass_handle=FALSE;
	}

	if(pass_handle){
		CreatePipe(&std_in[0], &std_in[1], &sa, 0);
		CreatePipe(&std_out[0], &std_out[1], &sa, 0);
		CreatePipe(&std_err[0], &std_err[1], &sa, 0);
		
		DuplicateHandle(
			GetCurrentProcess(),
			std_in[1],
			GetCurrentProcess(),
			&h_in,
			0,
			FALSE,
			DUPLICATE_SAME_ACCESS);
		CloseHandle(std_in[1]);
		
		DuplicateHandle(
			GetCurrentProcess(),
			std_out[0],
			GetCurrentProcess(),
			&h_out,
			0,
			FALSE,
			DUPLICATE_SAME_ACCESS);
		CloseHandle(std_out[0]);
		
		DuplicateHandle(
			GetCurrentProcess(),
			std_err[0],
			GetCurrentProcess(),
			&h_err,
			0,
			FALSE,
			DUPLICATE_SAME_ACCESS);
		CloseHandle(std_err[0]);
		
		si.dwFlags = STARTF_USESTDHANDLES;
		si.hStdInput = std_in[0];
		si.hStdOutput = std_out[1];
		si.hStdError = std_err[1];
	}
	
	success = CreateProcess(NULL, command_line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
	CloseHandle(pi.hThread);

	if(success)
    {
		if(s_task_flag & INI_WAITCHI) 
			WaitForSingleObject( pi.hProcess, INFINITE );
		CloseHandle(pi.hProcess);
		
		if(pass_handle){
			/* close already passed handles */
			CloseHandle(std_in[0]);
			CloseHandle(std_out[1]);
			CloseHandle(std_err[1]);
			
			*st_in = s_open_file_descripter(h_in, O_WRONLY, TRUE);
			*st_out = s_open_file_descripter(h_out, O_RDONLY, TRUE);
			*st_err = s_open_file_descripter(h_err, O_RDONLY, TRUE);
		}
	}
	else{
		char err_msg[256];
		sprintf(err_msg, "create process error command='%s'\n", command_line);
		print_win_error();
		er_panic(err_msg);
	}

	d_f_ree(command_line);
	return 0;
}
