[Opalvoip-svn] SF.net SVN: opalvoip:[34874] ptlib/trunk
Brought to you by:
csoutheren,
rjongbloed
From: <rjo...@us...> - 2016-07-14 17:02:20
|
Revision: 34874 http://sourceforge.net/p/opalvoip/code/34874 Author: rjongbloed Date: 2016-07-14 17:02:13 +0000 (Thu, 14 Jul 2016) Log Message: ----------- Added PPipeChannel::Run() to give similar functionality to Unix popen(). Modified Paths: -------------- ptlib/trunk/include/ptlib/pipechan.h ptlib/trunk/src/ptlib/msos/pipe.cxx ptlib/trunk/src/ptlib/unix/pipechan.cxx Modified: ptlib/trunk/include/ptlib/pipechan.h =================================================================== --- ptlib/trunk/include/ptlib/pipechan.h 2016-07-14 16:59:36 UTC (rev 34873) +++ ptlib/trunk/include/ptlib/pipechan.h 2016-07-14 17:02:13 UTC (rev 34874) @@ -378,6 +378,26 @@ PBoolean wait = false ///< Flag to indicate if function should block ); + /**Run the command synchonously and return the output. + Note it is expected that no output to the command is required, so stdin + will be EOF immediately. It is also expected that the command will run + to complation and all output, stdout and stderr, is captured to the + \p output parameter. + + @return + status code of the sub-process, if it ran to completion. If -1 then the + command failed to run at all. Other negative values indicates that the + process was terminated in an abnormal manner, e.g. crashed. The values + are platform specific, for Linux this is the negative value of signal + that the process was terminated with. + */ + static int Run( + const PString & command, ///< Command to execute + PString & output, ///< Output of command + bool includeStderr = true, ///< Include stderr in the above output + const PTimeInterval & timeout = PMaxTimeInterval ///< Timeout for waiting on output from sub-process + ); + /**Determine if the platform can support simultaneous read and writes from the PPipeChannel (eg MSDOS returns false, Unix returns true). Modified: ptlib/trunk/src/ptlib/msos/pipe.cxx =================================================================== --- ptlib/trunk/src/ptlib/msos/pipe.cxx 2016-07-14 16:59:36 UTC (rev 34873) +++ ptlib/trunk/src/ptlib/msos/pipe.cxx 2016-07-14 17:02:13 UTC (rev 34874) @@ -355,4 +355,20 @@ #endif // !_WIN32_WCE +int PPipeChannel::Run(const PString & command, PString & output, bool includeStderr, const PTimeInterval & timeout) +{ + PPipeChannel pipe; + pipe.SetReadTimeout(timeout); + + if (!pipe.Open(command, PPipeChannel::ReadOnly, true, !includeStderr) | !pipe.Execute()) + return -1; + + // Read until end of file, or timeout + output = pipe.ReadString(P_MAX_INDEX); + + // Wait for completion, which should have already happened + return pipe.WaitForTermination(1000); +} + + // End Of File /////////////////////////////////////////////////////////////// Modified: ptlib/trunk/src/ptlib/unix/pipechan.cxx =================================================================== --- ptlib/trunk/src/ptlib/unix/pipechan.cxx 2016-07-14 16:59:36 UTC (rev 34873) +++ ptlib/trunk/src/ptlib/unix/pipechan.cxx 2016-07-14 17:02:13 UTC (rev 34874) @@ -134,7 +134,7 @@ static const int TraceLevel = 5; if (PTrace::CanTrace(TraceLevel)) { ostream & log = PTRACE_BEGIN(TraceLevel); - log << "Forked child process \"" << subProgram << '"'; + log << "Forked child process (pid=" << m_childPID << ") \"" << subProgram << '"'; for (PINDEX i = 0; i < argumentList.GetSize(); ++i) log << " \"" << argumentList[i] << '"'; log << PTrace::End; @@ -481,3 +481,43 @@ } +int PPipeChannel::Run(const PString & command, PString & output, bool includeStderr, const PTimeInterval & timeout) +{ + output.MakeEmpty(); + + PString cmdWithStderr = command; + if (includeStderr) + cmdWithStderr += " 2>&1"; + FILE * pipe = popen(cmdWithStderr, "r"); + if (pipe == NULL) { + PTRACE(2, NULL, "Could not execute command [" << command << "] - " << strerror(errno)); + return -1; + } + + int c; + while ((c = fgetc(pipe)) != EOF) + output += (char)c; + + int status = pclose(pipe); + +#if PTRACING + ostream & trace = PTRACE_BEGIN(4); + trace << "Sub-process [" << command << "] executed: status=" << WEXITSTATUS(errorCode); + if (WIFSIGNALED(errorCode)) + trace << ", signal=" << WTERMSIG(errorCode); + if (WCOREDUMP(errorCode)) + trace << ", core dumped"; + } + trace << PTrace::End; +#endif + + if (WCOREDUMP(status)) + return INT_MIN; + + if (WIFSIGNALED(status)) + return - WTERMSIG(status); + + return WEXITSTATUS(status); +} + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |