#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#ifndef MVS
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif

#include <yafl_rnt.h>
#include "dbx_io.h"
#include "dbx_mess.h"
#include "dbx_envi.h"

/* this module selects the destination of the strings written by the */
/* debugger and the source of the strings read by the debugger in the */
/* command line interface;these source and destination are normally the */
/* standard input and output but when functionning in multi-console mode */
/* (when debugging applications using the curses library for example) */
/* the inputs and outputs of the debugger are redirected so as to not */
/* perturb the inputs and outputs of the debugged program */
/* we used named pipes created in a directory for temporary files */

#define MAX_CHARS 200
static char buffer[MAX_CHARS];
static char *pipe_name1,*pipe_name2;
static char *pipe_name3;

static char prefix[] = "/tmp/tube";
   
static int od,id;
static int cd;

dbx_message control_buffer;
#define CONTROL_SIZE (sizeof(dbx_message))

static int multi_mode;

#ifndef errno
extern int errno;
#endif

/* send a string either to standard output or to the first pipe,according */
/* to the mode */      
void send_string YPARAMS2(char *,  string)
{
  if (multi_mode)
  {
#ifdef UNIX    
#ifndef MVS
    control_buffer.command = 1;
    control_buffer.length = strlen(string);
    write(cd,&control_buffer,CONTROL_SIZE);
    write(od,string,strlen(string)); /* ??? */
#endif
#endif    
  }
  else
  {
    emit_stdout(string);
    fflush(stdout); /* it is useful to flush everything when debugging */
  }
}

/* receive a string either from standard input or from the second pipe, */
/* according to the mode */
char *receive_string YPARAMS0
{
  int count;
#ifdef UNIX  
#ifndef MVS
  if (multi_mode)
  {
    control_buffer.command = 0;
    write(cd,&control_buffer,CONTROL_SIZE);
    count = read(id,buffer,MAX_CHARS);
    if (count > 0)
      return (buffer);
    else
      return(NULL);
  }
  else     
#endif  
#endif
  {
    return(get_stdin(buffer));
  }          
}

/* try to find environment variable selecting mode of operation */
void init_dbx_io YPARAMS0
{
  int temp;
  int n;
  multi_mode = 0;
/* we effectively commute to multi mode only when the initialization */
/* process has correctly completed; if something fails during the */
/* initialization process we can still regain control of the debugger */
#ifdef UNIX
#ifndef MVS
  temp = envi_get_multi();
  if (temp)
  {  
    char * mktemp();

    n = strlen(prefix);

    pipe_name1 = mktemp("/tmp/tubeXXXXXX");
    if (!pipe_name1)
    {
      printf("cannot create temporary name\n");
      exit(EXIT_FAILURE);
    }
    if (mknod(pipe_name1, S_IFIFO | S_IRWXU | S_IRWXG | S_IRWXO, 0) != 0)
    {
      printf("cannot create pipe: %s \n", pipe_name1);
      printf("errno:  %d \n", errno);
      exit(EXIT_FAILURE);
    }

    pipe_name2 = mktemp("/tmp/tubeXXXXXX");
    if (!pipe_name2)
    {
      printf("cannot create temporary name\n");
      exit(EXIT_FAILURE);
    }
    if (mknod(pipe_name2, S_IFIFO | S_IRWXU | S_IRWXG | S_IRWXO, 0) != 0)
    {
      printf("cannot create pipe: %s \n", pipe_name2);
      printf("errno:  %d \n", errno);
      exit(EXIT_FAILURE);
    }

    pipe_name3 = mktemp("/tmp/tubeXXXXXX");
    if (!pipe_name3)
    {
      printf("cannot create temporary name\n");
      exit(EXIT_FAILURE);
    }

/*     pipe_name3 = "/home/bernard/pipe3"; */

    if (mknod(pipe_name3, S_IFIFO | S_IRWXU | S_IRWXG | S_IRWXO, 0) != 0)
    {
      printf("cannot create pipe: %s \n", pipe_name3);
      printf("errno:  %d \n", errno);
      exit(EXIT_FAILURE);
    }

     printf("launch consioc %s\n", pipe_name3 + n); 
/*     printf("launch consioc if not already done\n");  */

    cd = open(pipe_name3, O_WRONLY);
    if (cd == -1)
    {
      printf("cannot open control pipe: %s \n", pipe_name3);
      exit(EXIT_FAILURE);
    }
    strcpy(control_buffer.name, pipe_name1 + n);
    write(cd, &control_buffer, CONTROL_SIZE);
    od = open(pipe_name1, O_WRONLY);  
    if (od == -1)
    {
      printf("cannot open output pipe: %s \n", pipe_name1);
      exit(EXIT_FAILURE);
    }
    strcpy(control_buffer.name, pipe_name2 + n);
    write(cd, &control_buffer, CONTROL_SIZE);
    id = open(pipe_name2, O_RDONLY);
    if (id == -1)
    {
      printf("cannot open input pipe: %s \n", pipe_name2);
      exit(EXIT_FAILURE);
    }
  }
  multi_mode = temp;
#endif
#endif
}

/* close the pipes if they were open */
void term_dbx_io YPARAMS0
{
  if (multi_mode)
  {
#ifdef UNIX    
    close(cd);
    close(od); 
    close(id); 
    if (unlink(pipe_name3) != 0)
      printf("cannot unlink pipe: %s \n", pipe_name3);
    if (unlink(pipe_name1) != 0)
      printf("cannot unlink pipe: %s \n", pipe_name1);
    if (unlink(pipe_name2) != 0)
      printf("cannot unlink pipe: %s \n", pipe_name2);
#endif    
  }
}



