#include "amiga.h"
#include "processes.h"
#include "fifofd.h"
#include <amiga/ioctl.h>
#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <string.h>

struct pprocess
{
  struct pprocess *next;
  FILE *f;
  int pid;
};

static struct pprocess *_pplist;

FILE *popen(char *command, char *type)
{
  FILE *pipe;
  BPTR in, out;
  int close_in, close_out;
  char pname[24];
  struct pprocess *pp = (struct pprocess *)malloc(sizeof(struct pprocess));

  _sprintf(pname, "pipe:uxopen.%lx", _fifo_base + _fifo_offset++);

  if (type[0] == 'w' && type[1] == '\0')
    {
      pipe = fopen(pname, "w");
      out = Output(); close_out = FALSE;
      in = Open(pname, MODE_OLDFILE); close_in = TRUE;
    }
  else if (type[0] == 'r' && type[1] == '\0')
    {
      pipe = fopen(pname, "r");
      in = Input(); close_in = FALSE;
      out = Open(pname, MODE_NEWFILE); close_out = TRUE;
    }
  else
    {
      errno = EINVAL;
      return NULL;
    }

  if (!in || !out) _seterr();
  if (pipe && in && out && pp)
    {
      pp->pid = _start_process(command, in, close_in, out, close_out,
			       -1, FALSE, 0, 0);
      
      if (pp->pid)
	{
	  pp->next = _pplist;
	  _pplist = pp;
	  pp->f = pipe;

	  return pipe;
	}
    }
  if (pp) free(pp);
  if (in && close_in) Close(in);
  if (out && close_out) Close(out);
  if (pipe) fclose(pipe);

  return NULL;
}

int pclose(FILE *f)
{
  struct pprocess **scan = &_pplist;

  while (*scan)
    {
      if ((*scan)->f == f) /* found */
	{
	  struct pprocess *son = *scan;
	  int status;
	  int pid = son->pid;

	  *scan = son->next;	/* Remove process from list */

	  fclose(son->f);
	  free(son);
	  /* Wait for process to terminate */
	  if (waitpid(pid, &status, NULL) >= 0) return status;
	  return -1;
	}
      scan = &(*scan)->next;
    }
  return -1;
}
