
#include "config.h"
#include "yodl.h"
#include <fcntl.h>

#if 1
 /* urg */
void
gram_PIPETHROUGH ()
{
  char
   *cmd,			/* cmd as in yodl input file */
   *pipeto,			/* stuff to write to cmd */
   *inbuf,			/* buffer for cmd's output */
    tmpfile[255],		/* temp filename */
    syscmd[1000];		/* cmd as for popen() call */
  int count;
  int size;
  int fd[2];
  FILE
    * fcmd,			/* popen()-ed cmd */
    *foutput;			/* handle on child's output */
  struct stat
    statbuf;

  cmd = gram_parlist (builtin[idx_PIPETHROUGH], 1);
  cmd = gram_do_expand (cmd);

  /*
     urg:
       PIPETHROUGH(date)("").
   */

  while ((lextok == tok_space) 
         || (lextok == tok_newline))
    lexer ();

  pipeto = gram_parlist (builtin[idx_PIPETHROUGH], 1);

  message (3, "%s %s | %s\n", builtin[idx_PIPETHROUGH], str_short (cmd), str_short (pipeto)); 
	   
  if (!check_live_data (builtin[idx_PIPETHROUGH], cmd))
    {
      free (cmd);
      free (pipeto);
      return;
    }

#if 1
#ifdef __CYGWIN32__
  {
    
    char 
      pipecmd[BUFSIZ],
      tmpinput[BUFSIZ];
      
    FILE *fp;

    *pipecmd = '\0';
    *tmpinput = '\0';
    if (pipeto && *pipeto)
      {	
	
	sprintf (tmpinput, "%s/yodlinput.%d", TMPDIR, getpid ());
	if ( (fp = fopen( tmpinput, "w")) == (FILE*)NULL )
	  {
	    exit(1);
	  }
	fwrite( pipeto, strlen(pipeto), 1, fp );
	fclose( fp );
	sprintf( pipecmd, "< %s", tmpinput );
	free(pipeto);
      }
    sprintf (tmpfile, "%s/yodlpipe.%d", TMPDIR, getpid ());
    sprintf (syscmd, "%s %s > %s", cmd, pipecmd, tmpfile);
    free (cmd);
    system(syscmd);
    if( *tmpinput) unlink(tmpinput);
  }
#else
  /*
    URG, URG.  This *is* broken
   */
  sprintf (tmpfile, "%s/yodlpipe.%d", TMPDIR, getpid ());
  sprintf (syscmd, "%s > %s", cmd, tmpfile);
  free (cmd);

  if (!(fcmd = popen (syscmd, "w")))
    showchildstatus (-1, syscmd);	/* .. and exit */
  if (pipeto && *pipeto)
    {
      fputs (pipeto, fcmd);
      free (pipeto);
    }
  pclose (fcmd);
#endif /* __CYGWIN32__ */

  if (stat (tmpfile, &statbuf))	/* no output file */
    return;

  if (statbuf.st_size == 0)	/* empty output file */
    {
      unlink (tmpfile);
      return;
    }

  foutput = open_file (tmpfile, "r");	/* open child's output */
  inbuf = xrealloc (0, statbuf.st_size + 1);	/* prepare buffer */
  inbuf[statbuf.st_size] = '\0';
  fread (inbuf, statbuf.st_size, 1, foutput);	/* read in buffer */

  fclose (foutput);		/* clean up file */
  unlink (tmpfile);
#else

  if (pipe (fd))
    {
      perror ("pipe failed");
      return;
    }

  if (!(fcmd = popen (cmd, "w")))
    showchildstatus (-1, syscmd);	/* .. and exit */

  if (pipeto && *pipeto)
    fputs (pipeto, fcmd);
  pclose (fcmd);
  free (pipeto);

  free (cmd);
#endif

  lexer_pushstr (inbuf);	/* paste in buffer */
  free (inbuf);
}

#else


void
gram_PIPETHROUGH ()
{
  char *filter_cmd;		/* filter_cmd as in yodl input file */
  char *to_filter;		/* buffer for filter_cmd's input */
  char *from_filter;		/* buffer for filter_cmd's output */

  int nbytes;
  int size;

  int in[2];
  int out[2];
  int child_pid;

  filter_cmd = gram_parlist (builtin[idx_PIPETHROUGH], 1);
  filter_cmd = gram_do_expand (filter_cmd);

  /*
     urg:
       PIPETHROUGH(date)("").
   */

  while ((lextok == tok_space) 
         || (lextok == tok_newline))
    lexer ();

  to_filter = gram_parlist (builtin[idx_PIPETHROUGH], 1);

  message (3, "%s %s | %s\n", builtin[idx_PIPETHROUGH], str_short (filter_cmd), str_short (to_filter)); 
	   
  if (!check_live_data (builtin[idx_PIPETHROUGH], filter_cmd))
    {
      free (filter_cmd);
      free (to_filter);
      return;
    }

/*
   =========================================================
   Create two pipes:

   yodl                                     child process
   ----                                     -------------
   in
   in[1]  >-----------------------------------> in[0]
   out
   out[0]  <-----------------------------------< out[1]

   =========================================================
 */

  if (pipe (in) != 0)
    {
      perror ("tpipe");
      #if 0
      showchildstatus (-1, filter_cmd);	/* .. and exit */
      #endif
      exit (1);
    }
  if (pipe (out) != 0)
    {
      perror ("tpipe");
      exit (1);
    }

  if ((child_pid = fork ()) == 0)
    {
      dup2 (in[0], fileno (stdin));	/* child: replace stdin with in[0] */
      dup2 (out[1], fileno (stdout));	/* child: replace stdout with out[1] */
      dup2 (out[1], fileno (stderr));	/* you may not want this */

#if 0
	/* wants arguments separately... */
      if (execlp (filter_cmd, filter_cmd, (char *) 0))	/* run command */
#else
      if (system (filter_cmd))
#endif
	perror ("filter_cmd");
      exit (0);
    }

  if (to_filter && *to_filter)
    write (in[1], to_filter, strlen (to_filter));
  /* let child exit */
  close (in[1]);
  free (to_filter);

  size = 0;
  from_filter = malloc (BUFSIZ);
  fcntl (out[0], F_SETFL, O_NONBLOCK); 
  wait (0);
  nbytes = read (out[0], from_filter + size, BUFSIZ);
  printf ("BUFSIZ: %d\n", BUFSIZ);
  printf ("nbytes: %d, total: %d\n", nbytes, size);
  if (nbytes > 0)
    size += nbytes;
  while (nbytes > 0)
    {
      from_filter = xrealloc (from_filter, size + nbytes);
      nbytes = read (out[0], from_filter + size, BUFSIZ);
      printf ("nbytes: %d, total: %d\n", nbytes, size);
      if (nbytes > 0)
	size += nbytes;
    }
  from_filter[size] = '\0';

  kill (child_pid, SIGTERM);	/* Works fine on HPUX */
  /* Cygnus *broken* will not kill child */
  close (in[0]);
  close (in[1]);
  close (out[0]);
  close (out[1]);
  free (filter_cmd);

  lexer_pushstr (from_filter);	/* paste in buffer */
  free (from_filter);
}
#endif
