/* -*- mode: C -*-  Time-stamp: "2004-12-18 22:14:07 jemarch"
 *
 *      File:        hush.c
 *      Author:      Jose E. Marchesi <jemarch@gnu.org>
 *      Date:        9/2003
 *
 *      Common routines for hush.
 *
 */


#include "hush.h"


/* The current hush translator */
hushtrans_t curtrans;


/*
 *      Routine:      hush_init
 *      Purpose:
 *              Initializes hush
 *      Conditions:
 *              None
 *      Returns:
 *              None
 *
 */

void
hush_init (void)
{

  /* Initialize curtrans */
  curtrans.operation.goaway = NULL;
  curtrans.operation.read = NULL;
  curtrans.operation.write = NULL;
  curtrans.operation.exec = NULL;

} /* End of routine hush_init */


int
hush_lookup_on_op (char *opname)
{
  
  if (strcmp(opname, "read") == 0)
    {
      return on_read;
    }
  if (strcmp(opname, "write") == 0)
    {
      return on_write;
    }
  if (strcmp(opname, "exec") == 0)
    {
      return on_exec;
    }
  if (strcmp(opname, "goaway") == 0)
    {
      return on_goaway;
    }

  /* Invalid operation name */
  return on_undefined;

}



/*
 *      Routine:      hush_exec_on
 *      Purpose:
 *              Add an operation to curtrans
 *      Conditions:
 *              The global curtrans variable must be initialized.
 *      Returns:
 *              EXECUTION_SUCCESS or EXECUTION_FAILURE
 *
 */

int
hush_exec_on (COMMAND *on_command)
{
  int curop;

  /* Check the operation specified on the ON command */
  curop = hush_lookup_on_op(on_command->operation->word);
  switch(curop)
    {
    case on_read:
      {
	/* Create curtrans.operation.read */
	curtrans.operation.read = (hush_operation_t *) 
	  xmalloc(sizeof(hush_operation_t));

	/* Fill the iovar and the command */
	curtrans.operation.read->iovar = strdup (on_command->iovar->word);
	curtrans.operation.read->action = copy_command (on_command->action);

	/* Open read permissions */
	trivfs_support_read = 1;
/* 	trivfs_allow_open = trivfs_allow_open | O_READ; */

	break;
      }
    case on_write:
      {
	/* Create curtrans.operation.write */
	curtrans.operation.write = (hush_operation_t *) 
	  xmalloc(sizeof(hush_operation_t));

	/* Fill on the iovar and the command */
	curtrans.operation.write->iovar = strdup(on_command->iovar->word);
	curtrans.operation.write->action = copy_command (on_command->action);

	/* Open write permissions */
	trivfs_support_write = 1;
/* 	trivfs_allow_open = trivfs_allow_open | O_WRITE; */

	break;
      }
    case on_exec:
      {
	/* Create curtrans.operation.exec */
	curtrans.operation.exec = (hush_operation_t *)
	  xmalloc(sizeof(hush_operation_t));

	/* Fill on the action */
	curtrans.operation.exec->action = copy_command (on_command->action);

	/* Open exec permissions */
	trivfs_support_exec = 1;
/* 	trivfs_allow_open = trivfs_allow_open | O_EXEC; */

	break;
      }
    case on_goaway:
      {
	/* Create curtrans.operation.goaway */
	curtrans.operation.goaway = (hush_operation_t *)
	  xmalloc(sizeof(hush_operation_t));

	/* Fill on the action */
	curtrans.operation.goaway->action = copy_command (on_command->action);

	break;
      }

    case on_undefined:
      {
	return EXECUTION_FAILURE;
      }

    }

  return EXECUTION_SUCCESS;

} /* End of routine hush_exec_on */


/*
 *      Routine:      hush_exec_translate
 *      Purpose:
 *              Start translating, according to the 'curtrans'
 *              global variable.
 *              
 *      Conditions:
 *              The global variable curtrans must be initialized.
 *      Returns:
 *              Never returns.
 *
 */

int
hush_exec_translate (TRANSLATE_COM *translate_command)
{
  error_t retcode;

  mach_port_t bootstrap;
  struct trivfs_control *fsys;

  /* Get the bootstrap port */
  task_get_bootstrap_port (mach_task_self (), &bootstrap);
  if (bootstrap == MACH_PORT_NULL)
    {
      fprintf(stderr, "Must be started as a translator");
      jump_to_top_level(EXITPROG);
      /* Dragons here */
    }


  /* Reply to our parent */
  retcode = trivfs_startup (hush_bootstrap, 0, 0, 0, 0, 0, &fsys);
  mach_port_deallocate (mach_task_self (), hush_bootstrap);
  if (retcode)
    {
      fprintf(stderr, "trivfs_startup failed! Please note this is a panic error");
      return EXECUTION_FAILURE;
    }
  

  /* Launch the translator (and remember to piadously pray!) */
  ports_manage_port_operations_one_thread (fsys->pi.bucket,
					   trivfs_demuxer,
					   0);

  /* The translator has been terminated */
  jump_to_top_level(EXITPROG);
  
  /* Dragons here */

} /* End of routine hush_exec_translate */



/*** IO variables management ***/


/*
 *      Routine:      bind_iovar
 *      Purpose:
 *              Make an iovar available with a given value.
 *      Conditions:
 *              None
 *      Returns:
 *              The new shell variable
 *
 */

SHELL_VAR *
bind_iovar (char *name, char *value)
{

  return bind_variable(name, value);

} /* End of routine bind_iovar */


/*
 *      Routine:      unbind_iovar
 *      Purpose:
 *              Unbind the given iovar
 *      Conditions:
 *              None
 *      Returns:
 *              None
 *
 */

void
unbind_iovar (SHELL_VAR *iovar)
{
  
  unbind_variable(iovar->name);

} /* End of routine unbind_iovar */ 


/*
 *      Routine:      get_iovar_value
 *      Purpose:
 *              Get the given iovar value
 *      Conditions:
 *              None
 *      Returns:
 *              A string with the value.
 *
 */

char *
get_iovar_value (SHELL_VAR *iovar)
{

  return (get_variable_value(iovar));

} /* End of routine get_iovar_value */
