#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#define MAXFILE 65535

int pram_count;
char *path;
char *arg1;
char *arg2;
char *arg3;

void process_exit(int s)
{
	exit(0);
}

void child_fun()
{
	printf("child_fun. ppid %d\n", getppid());
	execl(path, arg1, arg2, arg3);
}

pid_t  fork_child()
{
	pid_t pid,pid_leader;
	pid = fork();
	if ( pid > 0)
	{
		return pid;
	}
	else if (pid == 0)
	{
		//让进程摆脱原会话的控制,让进程摆脱原进程组的控制,让进程摆脱原控制终端的控制
		pid_leader = setsid(); //第二步[1] 
		if ( pid_leader < 0)
			perror("setsid error");
		
		//重设文件权限掩码
		umask(0);
		printf("fork new child process.\n");
	}
	return pid;
}

void monitoring_child()
{
	pid_t child_process;
	int status;
	int signal_num;
	wait(&status); //等待子进程中断或终止，释放子进程资源，否则死掉的子进程会变成僵尸进程
	
	//如果子进程是由于某种信号退出的，捕获该信号
	if (WIFSIGNALED(status))
		signal_num = WTERMSIG(status);
	
	child_process = fork_child();
	if (child_process == 0)
	{
		printf("fork new child process.\n");
		child_fun();
	}
}

int main(int argc, char *args[]){ 
	
	pid_t pc,child_process;
	int i = 0;
	
	pc = fork(); //第一步
	if (pc<0){
		printf("error fork\n");
		exit(1);
	}
	else if (pc>0)
		exit(0);

	pram_count=argc;

	path = args[1];
	arg1 = args[2];
	arg2 = args[3];
	arg3 = args[4];
	
	signal(SIGCHLD, monitoring_child);
	signal(SIGTERM, process_exit);
	
	child_process = fork_child();
	if (child_process > 0)
	{
		while (1)
		{
			pause(); //主进程休眠，当有信号到来时被唤醒。
		}
	}
	
	return 0;
}
