stdout redirection for Unix
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_2_BRANCH@7490 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -78,11 +78,14 @@ public:
|
|||||||
#if wxUSE_STREAMS
|
#if wxUSE_STREAMS
|
||||||
// Pipe handling
|
// Pipe handling
|
||||||
wxInputStream *GetInputStream() const { return m_inputStream; }
|
wxInputStream *GetInputStream() const { return m_inputStream; }
|
||||||
|
wxInputStream *GetErrorStream() const { return m_errorStream; }
|
||||||
wxOutputStream *GetOutputStream() const { return m_outputStream; }
|
wxOutputStream *GetOutputStream() const { return m_outputStream; }
|
||||||
|
|
||||||
// implementation only (for wxExecute)
|
// implementation only (for wxExecute)
|
||||||
void SetPipeStreams(wxInputStream *inStream, wxOutputStream *outStream);
|
void SetPipeStreams(wxInputStream *inStream,
|
||||||
#endif
|
wxOutputStream *outStream,
|
||||||
|
wxInputStream *errStream);
|
||||||
|
#endif // wxUSE_STREAMS
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Init(wxEvtHandler *parent, int id, bool redirect);
|
void Init(wxEvtHandler *parent, int id, bool redirect);
|
||||||
@@ -90,9 +93,10 @@ protected:
|
|||||||
int m_id;
|
int m_id;
|
||||||
|
|
||||||
#if wxUSE_STREAMS
|
#if wxUSE_STREAMS
|
||||||
wxInputStream *m_inputStream;
|
wxInputStream *m_inputStream,
|
||||||
|
*m_errorStream;
|
||||||
wxOutputStream *m_outputStream;
|
wxOutputStream *m_outputStream;
|
||||||
#endif
|
#endif // wxUSE_STREAMS
|
||||||
|
|
||||||
bool m_redirect;
|
bool m_redirect;
|
||||||
};
|
};
|
||||||
|
@@ -98,6 +98,10 @@ public:
|
|||||||
wxListBox *GetLogListBox() const { return m_lbox; }
|
wxListBox *GetLogListBox() const { return m_lbox; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ShowOutput(const wxString& cmd,
|
||||||
|
const wxArrayString& output,
|
||||||
|
const wxString& title);
|
||||||
|
|
||||||
wxString m_cmdLast;
|
wxString m_cmdLast;
|
||||||
|
|
||||||
wxListBox *m_lbox;
|
wxListBox *m_lbox;
|
||||||
@@ -381,23 +385,15 @@ void MyFrame::OnExecWithRedirect(wxCommandEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
if ( sync )
|
if ( sync )
|
||||||
{
|
{
|
||||||
wxArrayString output;
|
wxArrayString output, errors;
|
||||||
int code = wxExecute(cmd, output);
|
int code = wxExecute(cmd, output);
|
||||||
wxLogStatus(_T("command '%s' terminated with exit code %d."),
|
wxLogStatus(_T("command '%s' terminated with exit code %d."),
|
||||||
cmd.c_str(), code);
|
cmd.c_str(), code);
|
||||||
|
|
||||||
if ( code != -1 )
|
if ( code != -1 )
|
||||||
{
|
{
|
||||||
m_lbox->Append(wxString::Format(_T("--- Output of '%s' ---"),
|
ShowOutput(cmd, output, _T("Output"));
|
||||||
cmd.c_str()));
|
ShowOutput(cmd, errors, _T("Errors"));
|
||||||
|
|
||||||
size_t count = output.GetCount();
|
|
||||||
for ( size_t n = 0; n < count; n++ )
|
|
||||||
{
|
|
||||||
m_lbox->Append(output[n]);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lbox->Append(_T("--- End of output ---"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // async exec
|
else // async exec
|
||||||
@@ -478,6 +474,26 @@ void MyFrame::OnProcessTerminated(MyPipedProcess *process)
|
|||||||
m_running.Remove(process);
|
m_running.Remove(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MyFrame::ShowOutput(const wxString& cmd,
|
||||||
|
const wxArrayString& output,
|
||||||
|
const wxString& title)
|
||||||
|
{
|
||||||
|
size_t count = output.GetCount();
|
||||||
|
if ( !count )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_lbox->Append(wxString::Format(_T("--- %s of '%s' ---"),
|
||||||
|
title.c_str(), cmd.c_str()));
|
||||||
|
|
||||||
|
for ( size_t n = 0; n < count; n++ )
|
||||||
|
{
|
||||||
|
m_lbox->Append(output[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lbox->Append(_T("--- End of output ---"));
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// MyProcess
|
// MyProcess
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -497,6 +513,8 @@ void MyProcess::OnTerminate(int pid, int status)
|
|||||||
|
|
||||||
bool MyPipedProcess::HasInput()
|
bool MyPipedProcess::HasInput()
|
||||||
{
|
{
|
||||||
|
bool hasInput = FALSE;
|
||||||
|
|
||||||
wxInputStream& is = *GetInputStream();
|
wxInputStream& is = *GetInputStream();
|
||||||
if ( !is.Eof() )
|
if ( !is.Eof() )
|
||||||
{
|
{
|
||||||
@@ -504,16 +522,28 @@ bool MyPipedProcess::HasInput()
|
|||||||
|
|
||||||
// this assumes that the output is always line buffered
|
// this assumes that the output is always line buffered
|
||||||
wxString msg;
|
wxString msg;
|
||||||
msg << m_cmd << _T(": ") << tis.ReadLine();
|
msg << m_cmd << _T(" (stdout): ") << tis.ReadLine();
|
||||||
|
|
||||||
m_parent->GetLogListBox()->Append(msg);
|
m_parent->GetLogListBox()->Append(msg);
|
||||||
|
|
||||||
return TRUE;
|
hasInput = TRUE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
wxInputStream& es = *GetErrorStream();
|
||||||
|
if ( !es.Eof() )
|
||||||
{
|
{
|
||||||
return FALSE;
|
wxTextInputStream tis(es);
|
||||||
|
|
||||||
|
// this assumes that the output is always line buffered
|
||||||
|
wxString msg;
|
||||||
|
msg << m_cmd << _T(" (stderr): ") << tis.ReadLine();
|
||||||
|
|
||||||
|
m_parent->GetLogListBox()->Append(msg);
|
||||||
|
|
||||||
|
hasInput = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return hasInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyPipedProcess::OnTerminate(int pid, int status)
|
void MyPipedProcess::OnTerminate(int pid, int status)
|
||||||
|
@@ -39,16 +39,18 @@ void wxProcess::Init(wxEvtHandler *parent, int id, bool redirect)
|
|||||||
|
|
||||||
#if wxUSE_STREAMS
|
#if wxUSE_STREAMS
|
||||||
m_inputStream = NULL;
|
m_inputStream = NULL;
|
||||||
|
m_errorStream = NULL;
|
||||||
m_outputStream = NULL;
|
m_outputStream = NULL;
|
||||||
#endif
|
#endif // wxUSE_STREAMS
|
||||||
}
|
}
|
||||||
|
|
||||||
wxProcess::~wxProcess()
|
wxProcess::~wxProcess()
|
||||||
{
|
{
|
||||||
#if wxUSE_STREAMS
|
#if wxUSE_STREAMS
|
||||||
delete m_inputStream;
|
delete m_inputStream;
|
||||||
|
delete m_errorStream;
|
||||||
delete m_outputStream;
|
delete m_outputStream;
|
||||||
#endif
|
#endif // wxUSE_STREAMS
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxProcess::OnTerminate(int pid, int status)
|
void wxProcess::OnTerminate(int pid, int status)
|
||||||
@@ -67,9 +69,14 @@ void wxProcess::Detach()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if wxUSE_STREAMS
|
#if wxUSE_STREAMS
|
||||||
void wxProcess::SetPipeStreams(wxInputStream *in_stream, wxOutputStream *out_stream)
|
|
||||||
|
void wxProcess::SetPipeStreams(wxInputStream *inputSstream,
|
||||||
|
wxOutputStream *outputStream,
|
||||||
|
wxInputStream *errorStream)
|
||||||
{
|
{
|
||||||
m_inputStream = in_stream;
|
m_inputStream = inputSstream;
|
||||||
m_outputStream = out_stream;
|
m_errorStream = errorStream;
|
||||||
|
m_outputStream = outputStream;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#endif // wxUSE_STREAMS
|
||||||
|
@@ -498,7 +498,7 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
|
|||||||
wxInputStream *inStream = new wxPipeInputStream(hpipeStdout[0]);
|
wxInputStream *inStream = new wxPipeInputStream(hpipeStdout[0]);
|
||||||
wxOutputStream *outStream = new wxPipeOutputStream(hpipeStdin[1]);
|
wxOutputStream *outStream = new wxPipeOutputStream(hpipeStdin[1]);
|
||||||
|
|
||||||
handler->SetPipeStreams(inStream, outStream);
|
handler->SetPipeStreams(inStream, outStream, NULL);
|
||||||
}
|
}
|
||||||
#endif // wxUSE_STREAMS
|
#endif // wxUSE_STREAMS
|
||||||
|
|
||||||
|
@@ -436,14 +436,18 @@ long wxExecute(wxChar **argv,
|
|||||||
}
|
}
|
||||||
#endif // wxUSE_GUI
|
#endif // wxUSE_GUI
|
||||||
|
|
||||||
int pipeIn[2];
|
// pipes for inter process communication
|
||||||
int pipeOut[2];
|
int pipeIn[2], // stdin
|
||||||
|
pipeOut[2], // stdout
|
||||||
|
pipeErr[2]; // stderr
|
||||||
|
|
||||||
pipeIn[0] = pipeIn[1] =
|
pipeIn[0] = pipeIn[1] =
|
||||||
pipeOut[0] = pipeOut[1] = -1;
|
pipeOut[0] = pipeOut[1] =
|
||||||
|
pipeErr[0] = pipeErr[1] = -1;
|
||||||
|
|
||||||
if ( process && process->IsRedirected() )
|
if ( process && process->IsRedirected() )
|
||||||
{
|
{
|
||||||
if ( pipe(pipeIn) == -1 || pipe(pipeOut) == -1 )
|
if ( pipe(pipeIn) == -1 || pipe(pipeOut) == -1 || pipe(pipeErr) == -1 )
|
||||||
{
|
{
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
// free previously allocated resources
|
// free previously allocated resources
|
||||||
@@ -476,6 +480,8 @@ long wxExecute(wxChar **argv,
|
|||||||
close(pipeIn[1]);
|
close(pipeIn[1]);
|
||||||
close(pipeOut[0]);
|
close(pipeOut[0]);
|
||||||
close(pipeOut[1]);
|
close(pipeOut[1]);
|
||||||
|
close(pipeErr[0]);
|
||||||
|
close(pipeErr[1]);
|
||||||
#endif // wxUSE_GUI
|
#endif // wxUSE_GUI
|
||||||
|
|
||||||
wxLogSysError( _("Fork failed") );
|
wxLogSysError( _("Fork failed") );
|
||||||
@@ -498,7 +504,7 @@ long wxExecute(wxChar **argv,
|
|||||||
{
|
{
|
||||||
for ( int fd = 0; fd < FD_SETSIZE; fd++ )
|
for ( int fd = 0; fd < FD_SETSIZE; fd++ )
|
||||||
{
|
{
|
||||||
if ( fd == pipeIn[0] || fd == pipeOut[1]
|
if ( fd == pipeIn[0] || fd == pipeOut[1] || fd == pipeErr[1]
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
|| fd == end_proc_detect[1]
|
|| fd == end_proc_detect[1]
|
||||||
#endif // wxUSE_GUI
|
#endif // wxUSE_GUI
|
||||||
@@ -514,19 +520,19 @@ long wxExecute(wxChar **argv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// redirect stdio and stdout
|
// redirect stdio, stdout and stderr
|
||||||
// (TODO: what about stderr?)
|
|
||||||
if ( pipeIn[0] != -1 )
|
if ( pipeIn[0] != -1 )
|
||||||
{
|
{
|
||||||
if ( dup2(pipeIn[0], STDIN_FILENO) == -1 ||
|
if ( dup2(pipeIn[0], STDIN_FILENO) == -1 ||
|
||||||
dup2(pipeOut[1], STDOUT_FILENO) == -1 )
|
dup2(pipeOut[1], STDOUT_FILENO) == -1 ||
|
||||||
|
dup2(pipeErr[1], STDERR_FILENO) == -1 )
|
||||||
{
|
{
|
||||||
wxLogSysError(_("Failed to redirect child process "
|
wxLogSysError(_("Failed to redirect child process input/output"));
|
||||||
"input/output"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close(pipeIn[0]);
|
close(pipeIn[0]);
|
||||||
close(pipeOut[1]);
|
close(pipeOut[1]);
|
||||||
|
close(pipeErr[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
execvp (*mb_argv, mb_argv);
|
execvp (*mb_argv, mb_argv);
|
||||||
@@ -544,10 +550,13 @@ long wxExecute(wxChar **argv,
|
|||||||
// These two streams are relative to this process.
|
// These two streams are relative to this process.
|
||||||
wxOutputStream *outStream = new wxProcessFileOutputStream(pipeIn[1]);
|
wxOutputStream *outStream = new wxProcessFileOutputStream(pipeIn[1]);
|
||||||
wxInputStream *inStream = new wxProcessFileInputStream(pipeOut[0]);
|
wxInputStream *inStream = new wxProcessFileInputStream(pipeOut[0]);
|
||||||
|
wxInputStream *errStream = new wxProcessFileInputStream(pipeErr[0]);
|
||||||
|
|
||||||
close(pipeIn[0]); // close reading side
|
close(pipeIn[0]); // close reading side
|
||||||
close(pipeOut[1]); // close writing side
|
close(pipeOut[1]); // close writing side
|
||||||
|
close(pipeErr[1]); // close writing side
|
||||||
|
|
||||||
process->SetPipeStreams(inStream, outStream);
|
process->SetPipeStreams(inStream, outStream, errStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
|
Reference in New Issue
Block a user