// ----------------------------------------------------------------------------
// FILE NAME: iextproc.hpp
//
// DESCRIPTION:
//
//  This module implements the IExternalProcess class, which is a simple
//  mechanism for executing and tracking external applications.
//
//  Each instance of IExternalProcess represents an instance of an external
//  process. That process might not be running at the time, i.e. the life
//  of the process handle class is not tied to the actual existence of the
//  external process. The reasons are that we cannot realistically force
//  the external process to terminate cleanly on demand and because there
//  is need for the starting process to get the termination codes, which
//  are stored in the process handle class after it terminates.
//
//  Because of the pretty massive differences in internal implementation,
//  IExternalProcess is mainly implemented in terms of a pure virtual
//  implementation class. According to the platform, the correct derivative
//  of this class is created and stored. The base implementation class is
//  called IExtProcImplBase
//
//  IExternalProcess will insure that calls to the implementation's start()
//  always have at least one argument. If none is provided by the user, then
//  a single argument of the path itself is provided.
//
//  When passing in command line parms, DO NOT put the process name as the
//  first parm. It will be added automatically internally, and will show up
//  as the 0th parm. So your passed in 0th parm, becomes the 1st one and so
//  on.
//
//
// COPYRIGHT:
//   IBM Open Class Library
//   Licensed Materials - Property of IBM
//
//   5645-001
//   (C) Copyright IBM Corporation 1992, 1997  All Rights Reserved.
//
// Revision: 44 1.3.1.2 source/core/base/iextproc.hpp, oss, portapak
// ----------------------------------------------------------------------------

#ifndef _IEXTPROC_
#define _IEXTPROC_

#include    <ipathnam.hpp>
#include    <ibhandle.hpp>
#include    <iprcenv.hpp>
#include    <ingapp.hpp>
#include    <itext.hpp>

#if __IBMCPP__ >= 400
#pragma namemangling(compat)
#endif

#pragma pack(push,4)
#pragma enum(4)

//
//  Abstract base implementation class via which IExternalProcess manages
//  its process. Derivatives of this class are provided for each platform
//  and the static IExternalProcess::makeImplObj() method creates a new one
//  for the current platform, which is why there is only a default
//  constructor BTW.
//
class IC_EXPORTB IExtProcImplBase
{
    public  :
                    IExtProcImplBase();
        virtual     ~IExtProcImplBase();

        // Getter methods
        IPathName   getPath() const;
        IProcessId  getId() const;

        // Setter methods
        void        setPath(const IPathName& newPath);
        void        setEnvironment(const IEnvironment& newEnv);

        void        throwIfRunning(const unsigned long reason) const;

        // These all have to be provided by derived class
        virtual INonGUIApplication::PriorityClass getPriority() const = 0;
        virtual bool exitStatus(unsigned long& status) const = 0;
        virtual bool isRunning() const = 0;
        virtual bool setPriority(INonGUIApplication::PriorityClass priority) = 0;
        virtual void start(const IText* argArray, const unsigned long argCount) = 0;
        virtual void kill() = 0;
        virtual bool wait(const long timeout) const = 0;


    protected   :
        // Let derived classes see this stuff
        void         setId(const IProcessId& newId);
        void         setIsRunning(const bool newState);
        IEnvironment fEnviron;

    private :
        // Don't expose these. Implemented in ibasecc.cpp right now!
                    IExtProcImplBase(const IExtProcImplBase&);
        void        operator=(const IExtProcImplBase&);

        // This stuff is platform independent enough to put here
        IPathName       fPath;
        IProcessId      fId;
};


//
//  This is the actual process handle class. It is very simple since
//  it is almost totally implemented in terms of the implementation
//  class, to which it delegates pretty much everthing.
//
class IC_EXPORTB IExternalProcess
{
    public :
        IExternalProcess();
        ~IExternalProcess();

        // Getter methods
        IPathName   getPath() const;
        IProcessId  getId() const;

        // Setter methods
        void        setPath(const IPathName& newName);
        void        setEnvironment(const IEnvironment& newEnv);

        // Process control methods
        virtual INonGUIApplication::PriorityClass getPriority() const;
        virtual bool exitStatus(unsigned long& status) const;
        virtual bool isRunning() const;
        virtual bool setPriority(INonGUIApplication::PriorityClass priority);
        virtual void start();
        virtual void start(const IPathName& path);
        virtual void start(const IPathName& path, const IText* argArray,
                             const unsigned long argCount);
        virtual void start(const IText* argArray, const unsigned long argCount);
        virtual void kill();
        virtual bool wait(const long timeout = -1) const;

        //
        //  Allocates and returns an implementation object for the current
        //  platform.
        //
        static IExtProcImplBase* makeImplObj();

    private :
        // Don't expose these. Implemented in ibasecc.cpp right now!
        IExternalProcess(const IExternalProcess&);
        void operator=(const IExternalProcess&);

        // Pointer to our implementation
        IExtProcImplBase*    fImpl;

    public:
        //
        //  Methods with obsolete names.  These are here to provide
        //  temporary compatibility with an early draft of the
        //  specification for this class.  Do not use in any new
        //  code.
        //
        inline bool        isStarted() const;
        inline void        stop();
        inline IProcessId  id() const;

};

#pragma enum(pop)
#pragma pack(pop)

#if __IBMCPP__ >= 400
#pragma namemangling()
#endif

#include <iextproc.inl>

#endif // _IEXTPROC_
