/* 
 * $Id: exec_proc.cpp,v 1.1 2003/06/20 09:18:41 mulix Exp $
 * Author: mulix <mulix@actcom.co.il>. public domain. 
 */ 

#include <iostream.h>

extern "C"{
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
}

const char* script_name = "hello.sh";


/* exec_process executs an executable or script.              */
/* params:                                                    */
/* char * name: the name of the process to execute            */
/* int * child_ret_value: will hold the process return value  */
/*                        IF IT EXITED SUCESSFULLY            */
/* char** argv: the arguments to pass to the process          */  
/* char** env: the enviroment to pass to the process          */
/*                                                            */        
/* the env parameter                                          */
/* return value: 1 if the child exited normally,              */
/*               0 if the child exited due to a signal        */
/* 	      -1 if there was an error                        */

int exec_process(const char* name, 
		 int* child_ret_value,
		 char* const argv[],
		 char* const env[] = NULL)
{
	pid_t new_proc;
	cout << "tying to fork: " << endl;
	if ((new_proc = fork()) == 0){
		/* fork was successfull, we're now in the child */
		/* try to execute the process */
		if (execve(name, argv, env) == -1){
			perror("execve failed");
			/* exit(255) to signal to our parent that we failed */
			/* to execute the process */
			exit(255);
		}
	} else if (new_proc == -1){
		/* fork failed*/
		perror("exec_process failed to fork");
		return -1;
	}
	/* we're in the parent */
	/* we now wait for the script to finish */
	int status = 0;
	pid_t wait_res;
	wait_res = waitpid(new_proc, &status, 0);
	if (wait_res == -1){
		perror("failed to wait for the child");
		return -1;
	}
	/* the process has finished */
	/* has it finished succesfully? */
	if (WIFEXITED(status) > 0){
		/* if the process failed to exec the script, we want to know */
		/* it will let us know by doing exit(255) */
		int exit_status = WEXITSTATUS(status);
		if (exit_status == 255){
			cout << "child failed to exec the script" << endl;
			return -1;
		}
		/* excellent, the child exited normally */
		cout << "child exited normally" << endl;
		if (child_ret_value){
			*child_ret_value = exit_status;
			cout << "child returned: " << *child_ret_value << endl;
		}
		return 1;
	}else{ /* child did not exit normally */
		cout << "child did not exit normally!" << endl;
		return 0;
	}
}

int main(int argc, char** argv)
{
	cout << "execing the script: " << script_name << endl;
	int ret_val = 0;
	char* new_argv[] = {(char*)script_name, '\0'}; 
	int res = exec_process(script_name, &ret_val, new_argv);
	cout << "execing the script returned: " << res << endl;
	if (res == 1)
		cout << "the script returned: " << ret_val << endl;
	return 0;
}



