// -*- c++ -*-
//------------------------------------------------------------------------------
// $Id: Pipe.h,v 1.2 2002/12/05 03:20:17 vlg Exp $
//------------------------------------------------------------------------------
//                           Pipe.h
//------------------------------------------------------------------------------
//  Copyright (C) 1997-2002  Vladislav Grinchenko <vladg@erols.com>
//
//  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.
//------------------------------------------------------------------------------
#ifndef PIPE_H
#define PIPE_H

#include <stdio.h>
#include <string>

#include "assa/Logger.h"

namespace ASSA {

/** @file Pipe.h
 * A wrapper around UNIX popen()/pclose() standard library calls.
 */

class Pipe 
{
public:
	/** 
	 * A no-op constructor 
	 */
	Pipe ();

	/**
	 * Destructor calls close () first in an attempt to close opened pipe.
	 */
	~Pipe ();

	/**
	 * Starts a subshell and feed it the string cmd_ to be executed.
	 * The pipe is created and attached to the standard input or standard
	 * output of the subprocess, according to whether type_ is either "r" 
	 * (read) or "w" (write). The other end of the pipe is returned to the 
	 * calling code as a standard I/O stream, FILE, ready for buffered use
	 * with fprintf(), fscanf(), fgets, etc.
	 *
	 * @see Fork
	 * @param cmd_ command to execute
	 * @param type_ "w" for write pipe and "r" for read pipe
	 * @return pointer to a standard I/O stream. In case of error,
	 * NULL is returned with errno set to indicate the type of error 
	 * encountered.
	*/
	FILE* open (const string& cmd_, const string& type_);

	/**
	 * Close the pipe. The subprocess' status is collected to ensure 
	 * that the child process have finished.
	 *
	 * @return 0 on success; -1 on error.
	*/
	  
	int close ();

	/**
	 * Kill subprocess with SIGTERM. You should most probably call
	 * close() afterwards to collect child process' status.
	 *
	 * @see close()
	 * @return 0 on success, -1 if kill(2) failed.
	*/
	int kill ();

	/** Get subprocess' PID. */
	pid_t pid () const;

	/** Get pipe's standard I/O file pointer */
	FILE* fp () const;

	/** Get pipe's file descriptor */
	int fd () const;

private:						
	Pipe (const Pipe&);
	Pipe& operator= (const Pipe&);

private:
	/**
	 * A standard I/O stream descriptor
	 */
	FILE*  m_fp;

	/**
	 * Supbrocess' PID
	 */
	pid_t  m_child_pid;
};

inline pid_t 
Pipe::pid () const { return m_child_pid; }

inline int
Pipe::fd () const { return fileno (m_fp); }

inline FILE*
Pipe::fp () const { return m_fp; }

} // end namespace ASSA

#endif // PIPE_H

