#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include "link.h"

void link_open(link_handle *l, char name[], char param[])
{
  pipe(l->pipefd1);
  pipe(l->pipefd2);
  if ((l->pid=fork())==0)	/* child  */
    {
      close(l->pipefd1[0]);
      close(1);
      dup(l->pipefd1[1]);
      close(2);
      dup(l->pipefd1[1]);
      close(l->pipefd2[1]);
      close(0);
      dup(l->pipefd2[0]);
      execlp(name, name, param, (char*)0);
    }
  else
    {
      l->fpin = fdopen(l->pipefd1[0], "r");
      l->fpout = fdopen(l->pipefd2[1], "w");
      close(l->pipefd1[1]);
      close(l->pipefd2[0]);
    }
}

void link_open2(link_handle *l, char name[], const char *params[])
{
  pipe(l->pipefd1);
  pipe(l->pipefd2);
  if ((l->pid=fork())==0)	/* child  */
    {
      close(l->pipefd1[0]);
      close(1);
      dup(l->pipefd1[1]);
      close(2);
      dup(l->pipefd1[1]);
      close(l->pipefd2[1]);
      close(0);
      dup(l->pipefd2[0]);
      execvp(name, params);
    }
  else
    {
      l->fpin = fdopen(l->pipefd1[0], "r");
      l->fpout = fdopen(l->pipefd2[1], "w");
      close(l->pipefd1[1]);
      close(l->pipefd2[0]);
    }
}

void link_close(link_handle *l)
{
  wait(NULL);/*(union  wait*)0);*/
  close(l->pipefd1[1]);
  close(l->pipefd2[0]);
  fclose(l->fpin);
  fclose(l->fpout);
  l->pid = 0;
}

int link_read(link_handle *l, char s[])
{
  int eof_flag;

  if (fgets(s, 100, l->fpin)==NULL)
    eof_flag = 1;	/*  linked -to process has terminated on its own. */
  else
    {
      s[strlen(s)-1]='\0';	/*  lose  the newline  character.  */
      eof_flag = 0;
    }
  return (eof_flag);
}

int link_input_waiting(link_handle *l)
{
  int num;

  ioctl(l->pipefd1[0], FIONREAD, &num);	/*  see  how many chars  in
					    buffer  */
  return  num;
}

void link_write_char(link_handle *l, char c)
{
  fprintf(l->fpout, "%c", c);
  fflush(l->fpout);
}

void link_write(link_handle *l, char s[])
{
  fprintf(l->fpout, "%s\n", s);
  fflush(l->fpout);
}

void link_kill(link_handle *l)
{
  kill(l->pid, SIGKILL);
  link_close(l);
}