+public:
+ wxStreamTempInputBuffer();
+
+ // call to associate a stream with this buffer, otherwise nothing happens
+ // at all
+ void Init(wxProcessFileInputStream *stream);
+
+ // check for input on our stream and cache it in our buffer if any
+ void Update();
+
+ ~wxStreamTempInputBuffer();
+
+private:
+ // the stream we're buffering, if NULL we don't do anything at all
+ wxProcessFileInputStream *m_stream;
+
+ // the buffer of size m_size (NULL if m_size == 0)
+ void *m_buffer;
+
+ // the size of the buffer
+ size_t m_size;
+};
+
+wxStreamTempInputBuffer::wxStreamTempInputBuffer()
+{
+ m_stream = NULL;
+ m_buffer = NULL;
+ m_size = 0;
+}
+
+void wxStreamTempInputBuffer::Init(wxProcessFileInputStream *stream)
+{
+ m_stream = stream;
+}
+
+void wxStreamTempInputBuffer::Update()
+{
+ if ( m_stream && m_stream->IsAvailable() )
+ {
+ // realloc in blocks of 4Kb: this is the default (and minimal) buffer
+ // size of the Unix pipes so it should be the optimal step
+ static const size_t incSize = 4096;
+
+ void *buf = realloc(m_buffer, m_size + incSize);
+ if ( !buf )
+ {
+ // don't read any more, we don't have enough memory to do it
+ m_stream = NULL;
+ }
+ else // got memory for the buffer
+ {
+ m_buffer = buf;
+ m_stream->Read((char *)m_buffer + m_size, incSize);
+ m_size += m_stream->LastRead();
+ }
+ }
+}
+
+wxStreamTempInputBuffer::~wxStreamTempInputBuffer()
+{
+ if ( m_buffer )
+ {
+ m_stream->Ungetch(m_buffer, m_size);
+ free(m_buffer);
+ }
+}
+
+#endif // wxUSE_STREAMS
+
+// ----------------------------------------------------------------------------
+// wxPipe: this encapsulates pipe() system call
+// ----------------------------------------------------------------------------
+
+class wxPipe
+{
+public:
+ // the symbolic names for the pipe ends
+ enum Direction
+ {
+ Read,
+ Write
+ };
+
+ enum
+ {
+ INVALID_FD = -1
+ };
+
+ // default ctor doesn't do anything
+ wxPipe() { m_fds[Read] = m_fds[Write] = INVALID_FD; }
+
+ // create the pipe, return TRUE if ok, FALSE on error
+ bool Create()
+ {
+ if ( pipe(m_fds) == -1 )
+ {
+ wxLogSysError(_("Pipe creation failed"));
+
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ // return TRUE if we were created successfully
+ bool IsOk() const { return m_fds[Read] != INVALID_FD; }
+
+ // return the descriptor for one of the pipe ends
+ int operator[](Direction which) const
+ {
+ wxASSERT_MSG( which >= 0 && (size_t)which < WXSIZEOF(m_fds),
+ _T("invalid pipe index") );
+
+ return m_fds[which];
+ }
+
+ // detach a descriptor, meaning that the pipe dtor won't close it, and
+ // return it
+ int Detach(Direction which)
+ {
+ wxASSERT_MSG( which >= 0 && (size_t)which < WXSIZEOF(m_fds),
+ _T("invalid pipe index") );
+
+ int fd = m_fds[which];
+ m_fds[which] = INVALID_FD;
+
+ return fd;
+ }
+
+ // close the pipe descriptors
+ void Close()
+ {
+ for ( size_t n = 0; n < WXSIZEOF(m_fds); n++ )
+ {
+ if ( m_fds[n] != INVALID_FD )
+ close(m_fds[n]);
+ }
+ }
+
+ // dtor closes the pipe descriptors
+ ~wxPipe() { Close(); }
+
+private:
+ int m_fds[2];
+};
+
+// ----------------------------------------------------------------------------
+// wxExecute: the real worker function
+// ----------------------------------------------------------------------------
+#ifdef __VMS
+#pragma message disable codeunreachable
+#endif
+
+long wxExecute(wxChar **argv,
+ int flags,
+ wxProcess *process)
+{
+ // for the sync execution, we return -1 to indicate failure, but for async
+ // case we return 0 which is never a valid PID
+ //
+ // we define this as a macro, not a variable, to avoid compiler warnings
+ // about "ERROR_RETURN_CODE value may be clobbered by fork()"
+ #define ERROR_RETURN_CODE ((flags & wxEXEC_SYNC) ? -1 : 0)
+
+ wxCHECK_MSG( *argv, ERROR_RETURN_CODE, wxT("can't exec empty command") );