 /*
  * Khoros: $Id: negotiator.c,v 1.2 1992/03/20 22:41:58 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: negotiator.c,v 1.2 1992/03/20 22:41:58 dkhoros Exp $";
#endif

 /*
  * $Log: negotiator.c,v $
 * Revision 1.2  1992/03/20  22:41:58  dkhoros
 * VirtualPatch5
 *
  */ 


/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 *
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "cantata.h"


/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>
   >>>>	    file name:  negotiator.c
   >>>>
   >>>>   description:
   >>>>
   >>>>      routines: 	xvl_negotiator_cb()
   >>>>			xvl_start_negotiator()
   >>>>                 xvl_stop_negotiator()
   >>>>                 xvl_clear_dispatched()
   >>>>
   >>>> modifications:
   >>>>
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */



/************************************************************
*
* Routine Name:  xvl_negotiator_cb
*
*      Purpose:  This routine is used to initialize the negotiation
*		 transport so that we will be able to negotiate sub-
*		 processes.
*
*        Input:  id  - the callback id
*		 fid - input file descriptor
*		 clientData - not used
*
*       Output:  none
*
*
*   Written By:  Mark Young
*
*************************************************************/


int xvl_negotiator_cb(id, fid, clientData)

int	id;
int	fid;
caddr_t clientData;
{
	Node  *node;
	Glyph *glyph;

	kfile *ifile, *ofile;
	int   pid, permanence, onum;
	char  buffer[MaxLength], command[MaxLength], filename[MaxLength];


	if (kget_negotiator(&ifile, &ofile) == -1)
	   return(False);

	if (kfgets(buffer, MaxLength, ifile) == NULL)
	   return(False);

	fprintf(stderr,"cantata: '%s'\n", buffer);
	if (sscanf(buffer,"%d%*[:]%*[ ]%[^' ]%*[ ]%*[']%[^']%*[']",
			&pid, command, filename) != 3)
	{
	   kfputs(buffer, ofile);
	   return(False);
	}

	permanence = ktransport_permanence(filename);
	if (!(node = xvl_find_onode(filename, main_workspace->running)) ||
	     node->glyph->pid != pid)
	{
	   kfputs("yes", ofile);
	   return(True);
	}

	glyph = node->glyph;
	if ((strcmp("open", command) == 0 && permanence == False) ||
	    (strcmp("close", command) == 0 && permanence == True))
	{
	   if (glyph->workspace->autorun == True)
	   {
	      xvl_clear_dispatched(glyph);
	      xvl_schedule_glyph(glyph);

	      xvl_autorun_dispatcher(glyph->workspace);
	   }
	}
	kfputs("yes", ofile);
	return(True);
}



/************************************************************
*
* Routine Name:  xvl_start_negotiator
*
*      Purpose:  This routine is used to initialize the negotiation
*		 transport so that we will be able to negotiate sub-
*		 processes.
*
*        Input:  none
*
*       Output:  none
*
*
*   Written By:  Mark Young
*
*************************************************************/


int xvl_start_negotiator()
{
	int	inum;
	kfile	*ifile;


	if (kstart_negotiator() == -1)
	   return(False);

	if (kget_negotiator(&ifile, NULL) == -1)
	   return(False);

	if (kdescriptors(ifile, &inum, NULL) == -1)
	   return(False);

	xvf_detect_fid(inum, xvl_negotiator_cb, NULL);
	return(True);
}



/************************************************************
*
* Routine Name:  xvl_stop_negotiator
*
*      Purpose:  This routine is used to terminate any negotiation
*		 between cantata's subprocesses and cantata itself.
*
*        Input:  none
*
*       Output:  none
*
*
*   Written By:  Mark Young
*
*************************************************************/


int xvl_stop_negotiator()
{
	kstop_negotiator();
	return(True);
}



/************************************************************
*
* Routine Name:  xvl_clear_dispatched
*
*      Purpose:  This routine is used to clear all children
*		 from the dispatched list, since this allows
*		 the negotiator to re-schedule children more
*		 than once (which the dispatched list is used
*		 so that implicit loops can be avoided).
*
*        Input:  glyph - the parent which will clear it's children
*
*       Output:  none
*
*
*   Written By:  Mark Young
*
*************************************************************/


static GlyphList *clear_dispatched(glyph, glyphlist)

Glyph *glyph;
GlyphList *glyphlist;
{
	Glyph	  *child;
	NodeList  *output;
	Workspace *workspace;


	if (glyph == NULL)
	   return(glyphlist);
	else if (xvl_check_if_glyphlist(glyph, glyphlist) == True)
	   return(glyphlist);
	else
	   glyphlist = xvl_add_to_glyphlist(glyph, glyphlist);

	/*
	 *  What we now need to do so that autorun will dispatch our
	 *  children is to remove all sub-processes from the dispatched
	 *  list.
	 */
	workspace = glyph->workspace;
	output = glyph->output_list;
	while (output != NULL)
	{
	   child = output->node->glyph;
	   if (xvl_check_if_glyphlist(child, workspace->dispatched) == True)
	   {
	      workspace->dispatched = xvl_delete_from_glyphlist(child,
                                workspace->dispatched);
	      glyphlist = clear_dispatched(child, glyphlist);
	   }
	   output = output->next;
	}
	return(glyphlist);
}

xvl_clear_dispatched(glyph)

Glyph *glyph;
{
	GlyphList *glyphlist = NULL;

	glyphlist = clear_dispatched(glyph, glyphlist);
	xvl_destroy_glyphlist(glyphlist);
}
