00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00038 #ifndef BLOCXX_EXEC_HPP_INCLUDE_GUARD_
00039 #define BLOCXX_EXEC_HPP_INCLUDE_GUARD_
00040
00041 #include "blocxx/BLOCXX_config.h"
00042 #include "blocxx/CommonFwd.hpp"
00043 #include "blocxx/EnvVars.hpp"
00044 #include "blocxx/Process.hpp"
00045 #ifdef BLOCXX_ENABLE_TEST_HOOKS
00046 #include "blocxx/GlobalPtr.hpp"
00047 #endif
00048
00049 namespace BLOCXX_NAMESPACE
00050 {
00051
00052 BLOCXX_DECLARE_APIEXCEPTION(ExecError, BLOCXX_COMMON_API);
00053 BLOCXX_DECLARE_APIEXCEPTION2(ExecTimeout, ExecErrorException, BLOCXX_COMMON_API);
00054 BLOCXX_DECLARE_APIEXCEPTION2(ExecBufferFull, ExecErrorException, BLOCXX_COMMON_API);
00055
00057 namespace Exec
00058 {
00084 BLOCXX_COMMON_API Process::Status system(const Array<String>& command,
00085 const char* const envp[] = 0, const Timeout& = Timeout::infinite);
00086
00087 template <typename SA1, typename SA2>
00088 Process::Status system(const SA1& command,
00089 const SA2& envVars, const Timeout& timeout = Timeout::infinite)
00090 {
00091 Cstr::CstrArr<SA1> sa_command(command);
00092 Cstr::CstrArr<SA2> sa_envVars(envVars);
00093 return system(sa_command.sarr, sa_envVars.sarr, timeout);
00094 }
00095
00097 BLOCXX_COMMON_API int safeSystem(const Array<String>& command,
00098 const char* const envp[] = 0) BLOCXX_DEPRECATED;
00099
00100
00105 class BLOCXX_COMMON_API PreExec
00106 {
00107 public:
00108 typedef ::BLOCXX_NAMESPACE::UnnamedPipe* pipe_pointer_t;
00109
00110 PreExec(bool precompute_max_descriptors = false);
00111
00112 virtual ~PreExec();
00113
00122 virtual bool keepStd(int d) const = 0;
00123
00124 struct Error
00125 {
00126 enum { MAX_MSG_LEN = 64 };
00127 char message[MAX_MSG_LEN + 1];
00128 int error_num;
00129 };
00130
00134 struct DontCatch
00135 {
00136 virtual ~DontCatch();
00137 };
00138
00158 virtual void call(pipe_pointer_t const pparr[]) = 0;
00159
00166 void closeDescriptorsOnExec(std::vector<bool> const & keep);
00167
00172 static void resetSignals();
00173
00180 static void closePipesOnExec(pipe_pointer_t const pparr[]);
00181
00189 static void setupStandardDescriptors(pipe_pointer_t const pparr[]);
00190
00197 static void setNewProcessGroup();
00198
00199 protected:
00200 long m_max_descriptors;
00201 };
00202
00205 static char const * const * const currentEnvironment = 0;
00206
00229 BLOCXX_COMMON_API ProcessRef spawn(
00230 char const * exec_path,
00231 char const * const argv[], char const * const envp[],
00232 PreExec & pre_exec
00233 );
00234
00246 template <typename S, typename SA1, typename SA2>
00247 ProcessRef spawn(
00248 S const & exec_path, SA1 const & argv, SA2 const & envp,
00249 PreExec & pre_exec
00250 )
00251 {
00252 Cstr::CstrArr<SA1> sa_argv(argv);
00253 Cstr::CstrArr<SA2> sa_envp(envp);
00254 char const * s_exec_path = Cstr::to_char_ptr(exec_path);
00255 return spawn(s_exec_path, sa_argv.sarr, sa_envp.sarr, pre_exec);
00256 }
00257
00259
00260 BLOCXX_COMMON_API ProcessRef spawn(
00261 char const * const argv[], char const * const envp[]
00262 );
00263
00271 template <typename SA1, typename SA2>
00272 ProcessRef spawn(
00273 SA1 const & argv, SA2 const & envp
00274 )
00275 {
00276 Cstr::CstrArr<SA1> sa_argv(argv);
00277 Cstr::CstrArr<SA2> sa_envp(envp);
00278 return spawn(sa_argv.sarr, sa_envp.sarr);
00279 }
00280
00281 template <typename SA1>
00282 ProcessRef spawn(
00283 SA1 const & argv
00284 )
00285 {
00286 return spawn(argv, Exec::currentEnvironment);
00287 }
00288
00316 BLOCXX_COMMON_API void gatherOutput(String& output, const ProcessRef& proc, const Timeout& timeout = Timeout::infinite, int outputlimit = -1);
00317
00318 enum EOutputSource
00319 {
00320 E_STDOUT,
00321 E_STDERR
00322 };
00323
00324 class BLOCXX_COMMON_API OutputCallback
00325 {
00326 public:
00327 virtual ~OutputCallback();
00328 void handleData(const char* data, size_t dataLen, EOutputSource outputSource, const ProcessRef& theProc, size_t streamIndex, Array<char>& inputBuffer);
00329 private:
00334 virtual void doHandleData(const char* data, size_t dataLen, EOutputSource outputSource, const ProcessRef& theProc, size_t streamIndex, Array<char>& inputBuffer) = 0;
00335 };
00336
00337 class BLOCXX_COMMON_API InputCallback
00338 {
00339 public:
00340 virtual ~InputCallback();
00341 void getData(Array<char>& inputBuffer, const ProcessRef& theProc, size_t streamIndex);
00342 private:
00343 virtual void doGetData(Array<char>& inputBuffer, const ProcessRef& theProc, size_t streamIndex) = 0;
00344 };
00345 #if 0
00346 enum EProcessRunning
00347 {
00348 E_PROCESS_RUNNING,
00349 E_PROCESS_EXITED
00350 };
00351
00352
00353 class ProcessStatus
00354 {
00355 public:
00356 ProcessStatus()
00357 : m_running(E_PROCESS_RUNNING)
00358 , m_status(0)
00359 {
00360 }
00361
00362 explicit ProcessStatus(int status)
00363 : m_running(E_PROCESS_EXITED)
00364 , m_status(status)
00365 {
00366 }
00367
00368 bool hasExited() const
00369 {
00370 return m_running == E_PROCESS_EXITED;
00371 }
00372
00373 const int& getStatus() const
00374 {
00375 return m_status;
00376 }
00377 private:
00378 EProcessRunning m_running;
00379 int m_status;
00380 };
00381 #endif
00382
00407 BLOCXX_COMMON_API void processInputOutput(OutputCallback& output, Array<ProcessRef>& procs,
00408 InputCallback& input, const Timeout& timeout = Timeout::infinite);
00409
00410
00411 BLOCXX_COMMON_API void processInputOutput(const String& input, String& output, const ProcessRef& process,
00412 const Timeout& timeout = Timeout::infinite, int outputlimit = -1);
00413
00449 BLOCXX_COMMON_API Process::Status feedProcessAndGatherOutput(
00450 ProcessRef const & proc, String & output,
00451 Timeout const & timeout = Timeout::infinite, int outputlimit = -1,
00452 String const & input = String());
00453
00492 BLOCXX_COMMON_API Process::Status feedProcessAndGatherOutput(
00493 ProcessRef const & proc, String & output,
00494 String & erroutput, Timeout const & timeout = Timeout::infinite,
00495 int outputLimit = -1,
00496 String const & input = String());
00497
00528 BLOCXX_COMMON_API Process::Status executeProcessAndGatherOutput(
00529 char const * const command[], String& output, char const * const envVars[],
00530 const Timeout& timeout = Timeout::infinite, int outputlimit = -1,
00531 char const * input = 0);
00532
00565 BLOCXX_COMMON_API Process::Status executeProcessAndGatherOutput(
00566 char const * const command[], String& output, String& erroutput,
00567 char const * const envVars[],
00568 const Timeout& timeout = Timeout::infinite, int outputLimit = -1,
00569 char const * input = 0);
00570
00575 template <typename SA1, typename S1, typename S2>
00576 Process::Status executeProcessAndGatherOutput(
00577 SA1 const & command, S1& output,
00578 const Timeout& timeout, int outputlimit, S2 const& input)
00579 {
00580 Cstr::CstrArr<SA1> sa_command(command);
00581 String tmpOutput;
00582 char const * sInput = Cstr::to_char_ptr(input);
00583 Process::Status res;
00584 try
00585 {
00586 res = executeProcessAndGatherOutput(sa_command.sarr, tmpOutput,
00587 currentEnvironment, timeout, outputlimit, sInput);
00588 }
00589 catch(...)
00590 {
00591 output = tmpOutput.c_str();
00592 throw;
00593 }
00594 output = tmpOutput.c_str();
00595 return res;
00596 }
00597
00603 template <typename SA1, typename S1, typename S2>
00604 Process::Status executeProcessAndGatherOutput(
00605 SA1 const & command, S1& output, S1& erroutput,
00606 const Timeout& timeout, int outputlimit, S2 const& input)
00607 {
00608 Cstr::CstrArr<SA1> sa_command(command);
00609 String tmpOutput, tmpErrOut;
00610 char const * sInput = Cstr::to_char_ptr(input);
00611 Process::Status res;
00612 try
00613 {
00614 res = executeProcessAndGatherOutput(sa_command.sarr, tmpOutput,
00615 tmpErrOut, currentEnvironment, timeout, outputlimit, sInput);
00616 }
00617 catch(...)
00618 {
00619 output = tmpOutput.c_str();
00620 erroutput = tmpErrOut.c_str();
00621 throw;
00622 }
00623 output = tmpOutput.c_str();
00624 erroutput = tmpErrOut.c_str();
00625 return res;
00626 }
00627
00632 template <typename SA1, typename S1>
00633 Process::Status executeProcessAndGatherOutput(
00634 SA1 const & command, S1& output,
00635 const Timeout& timeout = Timeout::infinite, int outputlimit = -1)
00636 {
00637 Cstr::CstrArr<SA1> sa_command(command);
00638 String tmpOutput;
00639 Process::Status res;
00640 try
00641 {
00642 res = executeProcessAndGatherOutput(sa_command.sarr, tmpOutput,
00643 currentEnvironment, timeout, outputlimit, (char const*)0);
00644 }
00645 catch(...)
00646 {
00647 output = tmpOutput.c_str();
00648 throw;
00649 }
00650 output = tmpOutput.c_str();
00651 return res;
00652 }
00653
00659 template <typename SA1, typename S1>
00660 Process::Status executeProcessAndGatherOutput(
00661 SA1 const & command, S1& output, S1& erroutput,
00662 const Timeout& timeout = Timeout::infinite, int outputlimit = -1)
00663 {
00664 Cstr::CstrArr<SA1> sa_command(command);
00665 String tmpOutput, tmpErrOut;
00666 Process::Status res;
00667 try
00668 {
00669 res = executeProcessAndGatherOutput(sa_command.sarr, tmpOutput,
00670 tmpErrOut, currentEnvironment, timeout, outputlimit,
00671 (char const*)0);
00672 }
00673 catch(...)
00674 {
00675 output = tmpOutput.c_str();
00676 erroutput = tmpErrOut.c_str();
00677 throw;
00678 }
00679 output = tmpOutput.c_str();
00680 erroutput = tmpErrOut.c_str();
00681 return res;
00682 }
00683
00697 template <typename SA1, typename S1, typename SA2, typename S2>
00698 Process::Status executeProcessAndGatherOutput(
00699 SA1 const & command, S1& output, SA2 const & envp,
00700 const Timeout& timeout, int outputlimit, S2 const& input)
00701 {
00702 Cstr::CstrArr<SA1> sa_command(command);
00703 Cstr::CstrArr<SA2> sa_envp(envp);
00704 String tmpOutput;
00705 char const * sInput = Cstr::to_char_ptr(input);
00706 Process::Status res;
00707 try
00708 {
00709 res = executeProcessAndGatherOutput(sa_command.sarr, tmpOutput, sa_envp.sarr,
00710 timeout, outputlimit, sInput);
00711 }
00712 catch(...)
00713 {
00714 output = tmpOutput.c_str();
00715 throw;
00716 }
00717 output = tmpOutput.c_str();
00718 return res;
00719 }
00720
00735 template <typename SA1, typename S1, typename SA2, typename S2>
00736 Process::Status executeProcessAndGatherOutput(
00737 SA1 const & command, S1& output, S1& erroutput, SA2 const & envp,
00738 const Timeout& timeout, int outputlimit, S2 const& input)
00739 {
00740 Cstr::CstrArr<SA1> sa_command(command);
00741 Cstr::CstrArr<SA2> sa_envp(envp);
00742 String tmpOutput, tmpErrOut;
00743 char const * sInput = Cstr::to_char_ptr(input);
00744 Process::Status res;
00745 try
00746 {
00747 res = executeProcessAndGatherOutput(sa_command.sarr, tmpOutput,
00748 tmpErrOut, sa_envp.sarr, timeout, outputlimit, sInput);
00749 }
00750 catch(...)
00751 {
00752 output = tmpOutput.c_str();
00753 erroutput = tmpErrOut.c_str();
00754 throw;
00755 }
00756 output = tmpOutput.c_str();
00757 erroutput = tmpErrOut.c_str();
00758 return res;
00759 }
00760
00765 template <typename SA1, typename S1, typename SA2>
00766 Process::Status executeProcessAndGatherOutput(
00767 SA1 const & command, S1& output, S1& erroutput, SA2 const & envp,
00768 const Timeout& timeout = Timeout::infinite, int outputlimit = -1)
00769 {
00770 return executeProcessAndGatherOutput(command, output, erroutput, envp,
00771 timeout, outputlimit, String());
00772 }
00773
00774
00775 BLOCXX_COMMON_API void executeProcessAndGatherOutput(
00776 const Array<String>& command,
00777 String& output, int& processstatus,
00778 int timeoutsecs = -1, int outputlimit = -1,
00779 const String& input = String()) BLOCXX_DEPRECATED;
00780
00781 namespace Impl
00782 {
00783
00784 unsigned const BLOCXX_IN = 0;
00785 unsigned const BLOCXX_OUT = 1;
00786 unsigned const BLOCXX_SERR = 2;
00787 unsigned const BLOCXX_EXEC_ERR = 3;
00788 unsigned const BLOCXX_NPIPE = 4;
00789 void close_child_ends(UnnamedPipeRef ppipe[BLOCXX_NPIPE]);
00790
00791 struct NullFactory
00792 {
00793 static void* create()
00794 {
00795 return 0;
00796 }
00797 };
00798 }
00799
00800 #ifdef BLOCXX_ENABLE_TEST_HOOKS
00801 typedef GlobalPtr<ExecMockObject, Impl::NullFactory> ExecMockObject_t;
00808 extern ExecMockObject_t g_execMockObject;
00809 #endif
00810 }
00811
00812 }
00813
00814 #endif