#ifndef __JSYSTEM__JPROCESS__ #define __JSYSTEM__JPROCESS__ #include #include "JLang/JException.hh" #include "JLang/JFileStreamBuffer.hh" /** * \author mdejong */ namespace JSYSTEM {} namespace JPP { using namespace JSYSTEM; } namespace JSYSTEM { using JLANG::JPipeOpenException; using JLANG::JForkException; using JLANG::JSystemException; using JLANG::JFileInputStreamBuffer; using JLANG::JFileOutputStreamBuffer; /** * Streaming of input and output from Linux command. */ class JProcess { public: /** * Default constructor. * This constructor starts an interactive shell. */ JProcess() : out (-1), err (-1), in (-1), gOut(NULL), gErr(NULL), gIn (NULL) { execute("/bin/tcsh", "tcsh", "-i", "-f"); } /** * Constructor. * * \param command Linux command */ JProcess(const std::string& command) : out (-1), err (-1), in (-1), gOut(NULL), gErr(NULL), gIn (NULL) { execute("/bin/tcsh", "tcsh", "-f", "-c", command.c_str()); } /** * Destructor. */ ~JProcess() { close(err); close(out); close(in); if (gOut != NULL) { delete gOut; } if (gErr != NULL) { delete gErr; } if (gIn != NULL) { delete gIn; } } /** * Get pointer to input stream buffer connected to the normal output stream. * * \param size size of internal buffers * \return pointer input stream buffer */ JFileInputStreamBuffer* getInputStreamBuffer(const std::size_t size = 65536) { if (gOut == NULL) { gOut = new JFileInputStreamBuffer(out, size); } return gOut; } /** * Get pointer to input stream buffer connected to the error output stream. * * \param size size of internal buffers * \return pointer to input stream buffer */ JFileInputStreamBuffer* getErrorStreamBuffer(const std::size_t size = 65536) { if (gErr == NULL) { gErr = new JFileInputStreamBuffer(err, size); } return gErr; } /** * Get pointer to output stream buffer connected to the normal input stream. * * \param size size of internal buffers * \return pointer to output stream buffer */ JFileOutputStreamBuffer* getOutputStreamBuffer(const std::size_t size = 65536) { if (gIn == NULL) { gIn = new JFileOutputStreamBuffer(in, size); } return gIn; } protected: /** * Execute command. * * \param path path * \param arg0 comma separted argument list * \param arg1 comma separted argument list * \param arg2 comma separted argument list * \param arg3 comma separted argument list * \param arg4 comma separted argument list * \param arg5 comma separted argument list * \param arg6 comma separted argument list * \param arg7 comma separted argument list * \param arg8 comma separted argument list * \param arg9 comma separted argument list */ void execute(const char* path, const char* arg0, const char* arg1 = (char*) NULL, const char* arg2 = (char*) NULL, const char* arg3 = (char*) NULL, const char* arg4 = (char*) NULL, const char* arg5 = (char*) NULL, const char* arg6 = (char*) NULL, const char* arg7 = (char*) NULL, const char* arg8 = (char*) NULL, const char* arg9 = (char*) NULL) { int pipe_stdin [2]; int pipe_stdout[2]; int pipe_stderr[2]; if (pipe(pipe_stdin)) { throw JPipeOpenException("Error at pipe of standard input."); } if (pipe(pipe_stdout)) { throw JPipeOpenException("Error at pipe of standard output."); } if (pipe(pipe_stderr)) { throw JPipeOpenException("Error at pipe of standard error."); } const pid_t pid = fork(); if (pid < 0) // error throw JForkException("JProcess::fork() failed"); else if (pid == 0) { // child close(pipe_stdin [1]); if (dup2 (pipe_stdin [0], STDIN_FILENO) == -1) { JSystemException("dup2-stdin"); } close(pipe_stdout[0]); if (dup2 (pipe_stdout[1], STDOUT_FILENO) == -1) { JSystemException("dup2-stdout"); } close(pipe_stdout[0]); if (dup2 (pipe_stdout[1], STDERR_FILENO) == -1) { JSystemException("dup2-stderr"); } execl(path, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, (char*) NULL); throw JSystemException(path); } else { // parent in = pipe_stdin [1]; out = pipe_stdout[0]; err = pipe_stderr[0]; close(pipe_stdin [0]); close(pipe_stdout[1]); close(pipe_stderr[1]); } } int out; int err; int in; private: JFileInputStreamBuffer* gOut; JFileInputStreamBuffer* gErr; JFileOutputStreamBuffer* gIn; JProcess(const JProcess&); JProcess(JProcess&&); JProcess& operator=(const JProcess&); JProcess& operator=(JProcess&&); }; } #endif