/****************************************************************************
 * This file was derived from the CNCL library by the Pablo research group.
 *
 * The complete CNCL library is available at:
 *       http://www.comnets.rwth-aachen.de/doc/cncl.html
 *
 * The CNCL copyright notice is included here:
 *
 * |_|_|_  |_|_    |_    |_|_|_  |_               C O M M U N I C A T I O N
 *|_       |_  |_  |_  |_        |_                         N E T W O R K S
 *|_       |_  |_  |_  |_        |_                               C L A S S
 * |_|_|_  |_    |_|_    |_|_|_  |_|_|_|_                     L I B R A R Y
 *
 *
 *
 * Copyright (C) 1992-1998   Communication Networks
 *                           Aachen University of Technology
 *                           D-52056 Aachen
 *                           Germany
 *                           Email: cncl-adm@comnets.rwth-aachen.de
 *
 *
 * This library is free  software; you can  redistribute it and/or modify
 * it  under   the terms  of the GNU   Library  General Public License as
 * published by the  Free Software Foundation;  either  version 2 of  the
 * License, or  (at  your option)  any  later  version.  This  library is
 * distributed  in the  hope  that  it  will  be useful,  but WITHOUT ANY
 * WARRANTY;  without even the   implied  warranty of MERCHANTABILITY  or
 * FITNESS FOR A PARTICULAR PURPOSE.   See the GNU Library General Public
 * Library General Public License along with  this library; if not, write
 * to the Free Software Foundation,  675  Mass Ave, Cambridge, MA  02139,
 * USA.
 ****************************************************************************/

//   -*- C++ -*-
/*****************************************************************************
 *
 * Class: FlPipe --- UNIX pipe
 *
 *****************************************************************************/

#include "FlPipe.h"

#include <assert.h>
#include <unistd.h>
#include <sys/wait.h>

using std::cerr;
using std::endl;
 
/*
 * Constructors
 */
FlPipe::FlPipe()
    : pid(-1), program(""), sin(NIL), sout(NIL)
{
}


FlPipe::FlPipe(const FlString& prog)
    : pid(-1), program(""), sin(NIL), sout(NIL)
{
    open(prog);
}



/*
 * Open pipe to program
 */
int FlPipe::open(const FlString &prog)
{
    int to[2], from[2];

    cerr << "FlPipe::open has not been ported to use Standard Streams\n";
    cerr << "Exiting application\n";
    assert( 0 );

    program = prog;
    if(pid != -1)
	close();

    /*
     * Create pipe via pipe() system call
     *   fd[0] - read
     *   fd[1] - write
     */
    if(pipe(to))
    {
	error(NIL, "FlPipe: ", "can't create pipe to program");
	return -1;
    }
    if(pipe(from))
    {
	error(NIL, "FlPipe: ", "can't create pipe from program");
	return -1;
    }

    /*
     * Fork child and attach pipe to stdin/stdout
     */
    pid = fork();
    if (pid == -1)
    {
	error(NIL, "FlPipe: ", "error in fork()");
	return -1;
    }
    if(pid == 0)
    {
	/* The child process */
	if(dup2(to[0], 0) != 0)
	{
	    fatal(NIL, "FlPipe: ", "can't attach pipe to stdin");
	}
	::close(to[0]);
	::close(to[1]);
	
	if(dup2(from[1], 1) != 1)
	{
	    fatal(NIL, "FlPipe: ", "can't attach pipe to stdout");
	}
	::close(from[0]);
	::close(from[1]);

	execlp(program, program, NIL);	
	
	/* In case execlp() failed */
	fatal(NIL, "FlPipe: ", "can't exec ", program);
    }
    else
    {
        #ifdef NOTDEF
        // XXX: disable for now
	/* The parent process */
	::close(to[0]);
	fdout = to[1];
	sout = new ofstream(to[1]);	// Output stream
	if(sout->fail())
	{
	    error(NIL, "FlPipe: ", "can't open output stream");
	    return -1;
	}
	::close(from[1]);
	fdin = from[0];
	sin  = new ifstream(from[0]);	// Input stream
	if(sin->fail())
	{
	    error(NIL, "FlPipe: ", "can't open input stream");
	    return -1;
	}
        #endif
    }

    return 0;
}



/*
 * Close pipe
 */
int FlPipe::close()
{
    int status;
    
    if(pid != -1)
    {
	/*
	 * Close pipe
	 */
	::close(fdin);
	::close(fdout);
	delete(sin);
	delete(sout);
	pid = -1;
	program = "";
	
	/*
	 * Wait for child to exit
	 */
	waitpid(pid, &status, 0);
	if(WIFEXITED(status) && WEXITSTATUS(status))
	{
	    error(NIL, "FlPipe: ", "child exited with error status");
	    return -1;
	}
    }
    
    return 0;
}



/***** Default I/O member function for FuzzyLib classes **************************/

// Normal output
void FlPipe::print(ostream &strm) const
{
    strm << "program=" << program << " pid=" << pid
	 << " fdin=" << fdin << " fdout=" << fdout <<endl;
}

// Debug output
void FlPipe::dump(ostream &strm) const
{
    strm << "FlPipe { $Revision: 1.3 $ " << endl;
    print(strm);
    strm << "}" << endl;
}






