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

child.hpp

introduces the child class. Provides functions for handling
child processes.

resources used:  This makes use of the SIGUSR1 and SIGCHLD signals: 
				DO NOT attempt to use these signals, or odd behaviour may result.

other notes:
				IF a particular process happens to be an intermediate master, i.e.
				it is created by a master process and has children of its own, in order
				to properly handle the death of children, it should declare its DML_child
				objects BEFORE declaring its DML_master object.
				
				
Author: Ryan Findley


History:
who	when		what
--------------------------------
ryan	5/10/99		started

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

#ifndef CHILD_HPP
#define CHILD_HPP


#include <sys/proxy.h>
#include <process.h>
#include <sys/psinfo.h>
#include <sys/types.h>
#include <signal.h>



//------------------- definitions --------------------
#define QUIET 1
#define LOUD  0
#define MAX_N_CHILD 256
#define MAX_CHILD_NAME_LENGTH 255
#define WAIT_RESPONSE 1
#define DONT_WAIT 0

//------------------- typedefs -----------------------


//structure used to pass info back and forth to the child.
typedef struct 
{
    pid_t proxy;
    int priority;
    int verbosity;
    
} childInfoStruct;

//------------------- public prototypes --------------

//------------------- class definitions --------------

//Now remember, the Master process creates an instance of the child class to talk to the child,
//and the child process creates an instance of the master class.   :-)
class DML_child
{
  public:
    
    pid_t id;						//the child's process ID
    pid_t proxy;					//a proxy attached to the child
    int priority;					//the child's priority    			
    char name[MAX_CHILD_NAME_LENGTH+1];	//the file from which the child came
    int flags;						//flags for child creation (normally don't play with these)
	        
    DML_child();					//creates a blank child instance
    DML_child(char * theName, 
		int theVerbosity = LOUD, 
		int waitforResponse = DONT_WAIT);	//creates a child instance from file "name"
    ~DML_child();					//destructor
    
    open(char * theName);			//starts the child process running.
    sendInfoMsg();					//sends the info message to the process, gets the reply
    int sendMsg(int theMsg);		//sends an integer message (the most common). 
									//Typically used for status exchange.
    								//returns the reply message.    
    
    int beQuiet();					//suppresses printf messages in member functions. returns previous verbosity.
    								//passes on low verbosity to child, but the child is free to do with it as it pleases.
    int beLoud();					//opposite of beQuiet. returns previous verbosity
    
    attachProxy();					//attaches a proxy to the child
    int kick();						//triggers the proxy which is attached to the child.
    DML_child & print();			//prints info about the child.
	
	    
	static killChildren();
	static printChildren();	
	
			  
  private:
    childInfoStruct msg, rmsg;		//used for messaging
    int verbosity;					//child can use this to determine whether or not to be verbose
	int childNum;					//index in the theChildren array
	static int nChildren;   
	static DML_child **theChildren; //pointer to DML_child objects
	static void childDeathHandler(int sig_count);    
};


class DML_master
{
public: 
    static pid_t id;		//this is the master PID
    pid_t proxy;			//this is the proxy that the MASTER will use to kick the child
    int verbosity;
    int priority;
    
    DML_master();			//default constructor
    sendInfoMsg();			//gets that nefarious info message that a new child and master communicate with.
    int getMsg(int rMsg);	//gets an expected integer message from the master: sends back the rmsg.
	    
};
	
#endif  //CHILD_HPP