// -*- c++ -*-

/*
 * Jakelib2 - General purpose C++ library
 * Copyright (C) 2001 Florian Wolff  (florian@donuz.de)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: Process.h,v 1.28 2003/09/02 10:02:52 florian Exp $
 */

#ifndef INCLUDE_JAKELIB2_LANG_PROCESS_H
# define INCLUDE_JAKELIB2_LANG_PROCESS_H

# ifdef HAVE_UNISTD_H
#  include <unistd.h>
# endif
# if defined(JAKELIB_WIN32API)
#  include <windows.h>
# endif

namespace jakelib
{
  namespace io
  {
    class OutputStream;
    class InputStream;
  }
  namespace lang
  {

    /**
     * An instance of \c Process can be used to start a native process,
     * watch its output and pass input.
     * 
     * \b Example:
     * \code
     *   Process process = new Process("ls", "-l", "-a", null);
     *   InputStream* input = process->getInputStream();
     *   process->waitFor();
     *   int rc = process.exitValue();
     * \endcode
     *
     * @class Process
     * @version $Id: Process.h,v 1.28 2003/09/02 10:02:52 florian Exp $
     * @author Florian 'Overflo' Wolff (florian@donuz.de)
     * @since 1.1.0
     */
    class Process:public Object
    {
    public:
      /**
       * The given program is executed, the argument list must end in a \c null
       * element.
       *
       * @param progname Filename of the program to be executed
       * @param ... <tt>null</tt>-terminated argument list
       */
      Process(String * progname, ...);

      ~Process();

      /**
       * @brief Gets the output stream of the subprocess' <tt>stdin</tt> stream.
       */
      jakelib::io::OutputStream * getOutputStream();

      /**
       * @brief Gets the input stream for the subprocess' <tt>stdout</tt> stream.
       */
      jakelib::io::InputStream * getInputStream();
      
      /**
       * @brief Gets the input stream for the subprocess' <tt>stderr</tt> stream.
       */
      jakelib::io::InputStream * getErrorStream();

      /**
       * @brief Kills the subprocess.
       */
      void destroy();
      
      /**
       * @brief Waits - if necessary - for the subprocess to terminate.
       */
      void waitFor();

      /**
       * @brief Returns the exit value of the subprocess.
       *
       * @throws IllegalThreadStateException If the process has not yet terminated.
       */
      int exitValue();

    protected:

      /** Holds the process' stdout stream */
      jakelib::io::OutputStream * outputStream;

      /** Holds the process' stdin stream */
      jakelib::io::InputStream * inputStream;

      /** Holds the process' stderr stream */
      jakelib::io::InputStream * errorStream;

    private:

#if defined(JAKELIB_WIN32API)
      PROCESS_INFORMATION procInfo;
      DWORD _exitValue;

      /** StdOut pipe (stdin for the child process) */
      HANDLE outPipe;

      /** StdErr pipe (stderr for the child process) */
      HANDLE errPipe;

      /** StdIn pipe (stdout for the child process) */
      HANDLE inPipe;
#else
      pid_t childPid;
      int _exitValue;

      /** StdOut pipe (stdin for the child process) */
      int outPipe;

      /** StdErr pipe (stderr for the child process) */
      int errPipe;

      /** StdIn pipe (stdout for the child process) */
      int inPipe;
#endif
      jboolean terminated;

      JAKELIB_DECLARE_CLASS(Process);
    };
  }
}

#endif
