Ejemplo n.º 1
0
int hb_fsProcessRun( const char * pszFileName,
                     const char * pStdInBuf, HB_SIZE nStdInLen,
                     char ** pStdOutPtr, HB_SIZE * pulStdOut,
                     char ** pStdErrPtr, HB_SIZE * pulStdErr,
                     HB_BOOL fDetach )
{
   HB_FHANDLE hStdin, hStdout, hStderr, *phStdin, *phStdout, *phStderr;
   char * pOutBuf, *pErrBuf;
   HB_SIZE nOutSize, nErrSize, nOutBuf, nErrBuf;
   int iResult;

   HB_TRACE( HB_TR_DEBUG, ( "hb_fsProcessRun(%s, %p, %" HB_PFS "u, %p, %p, %p, %p, %d)", pStdInBuf, pStdInBuf, nStdInLen, pStdOutPtr, pulStdOut, pStdErrPtr, pulStdErr, fDetach ) );

   nOutBuf = nErrBuf = nOutSize = nErrSize = 0;
   pOutBuf = pErrBuf = NULL;
   hStdin = hStdout = hStderr = FS_ERROR;
   phStdin = pStdInBuf ? &hStdin : NULL;
   phStdout = pStdOutPtr && pulStdOut ? &hStdout : NULL;
   phStderr = pStdErrPtr && pulStdErr ?
              ( pStdOutPtr == pStdErrPtr ? phStdout : &hStderr ) : NULL;

#if defined( HB_PROCESS_USEFILES )
{

#if defined( HB_OS_WIN_CE )
#  define _HB_NULLHANDLE()    FS_ERROR
#elif defined( HB_OS_UNIX )
#  define _HB_NULLHANDLE()    open( "/dev/null", O_RDWR )
#else
#  define _HB_NULLHANDLE()    open( "NUL:", O_RDWR )
#endif
   char sTmpIn[ HB_PATH_MAX ];
   char sTmpOut[ HB_PATH_MAX ];
   char sTmpErr[ HB_PATH_MAX ];

   HB_SYMBOL_UNUSED( phStdin );
   HB_SYMBOL_UNUSED( nOutSize );
   HB_SYMBOL_UNUSED( nErrSize );

   sTmpIn[ 0 ] = sTmpOut[ 0 ] = sTmpErr[ 0 ] = '\0';
   if( pStdInBuf )
   {
      hStdin = hb_fsCreateTempEx( sTmpIn, NULL, NULL, NULL, FC_NORMAL );
      if( nStdInLen )
      {
         hb_fsWriteLarge( hStdin, pStdInBuf, nStdInLen );
         hb_fsSeek( hStdin, 0, FS_SET );
      }
   }
   else if( fDetach )
      hStdin = _HB_NULLHANDLE();

   if( pStdOutPtr && pulStdOut )
      hStdout = hb_fsCreateTempEx( sTmpOut, NULL, NULL, NULL, FC_NORMAL );
   else if( fDetach )
      hStdout = _HB_NULLHANDLE();

   if( pStdErrPtr && pulStdErr )
   {
      if( phStdout == phStderr )
         hStderr = hStdout;
      else
         hStderr = hb_fsCreateTempEx( sTmpErr, NULL, NULL, NULL, FC_NORMAL );
   }
   else if( fDetach )
      hStderr = _HB_NULLHANDLE();

   iResult = hb_fsProcessExec( pszFileName, hStdin, hStdout, hStderr );

   if( hStdin != FS_ERROR )
   {
      hb_fsClose( hStdin );
      if( sTmpIn[ 0 ] )
         hb_fsDelete( sTmpIn );
   }
   if( hStdout != FS_ERROR )
   {
      if( pStdOutPtr && pulStdOut )
      {
         nOutBuf = hb_fsSeek( hStdout, 0, FS_END );
         if( nOutBuf )
         {
            pOutBuf = ( char * ) hb_xgrab( nOutBuf + 1 );
            hb_fsSeek( hStdout, 0, FS_SET );
            nOutBuf = hb_fsReadLarge( hStdout, pOutBuf, nOutBuf );
         }
      }
      hb_fsClose( hStdout );
      if( sTmpOut[ 0 ] )
         hb_fsDelete( sTmpOut );
   }
   if( hStderr != FS_ERROR && hStderr != hStdout )
   {
      if( pStdErrPtr && pulStdErr )
      {
         nErrBuf = hb_fsSeek( hStderr, 0, FS_END );
         if( nErrBuf )
         {
            pErrBuf = ( char * ) hb_xgrab( nErrBuf + 1 );
            hb_fsSeek( hStderr, 0, FS_SET );
            nErrBuf = hb_fsReadLarge( hStderr, pErrBuf, nErrBuf );
         }
      }
      hb_fsClose( hStderr );
      if( sTmpErr[ 0 ] )
         hb_fsDelete( sTmpErr );
   }
}

#else /* ! HB_PROCESS_USEFILES */
{
   HB_FHANDLE hProcess;

   hb_vmUnlock();

   iResult = -1;
   hProcess = hb_fsProcessOpen( pszFileName, phStdin, phStdout, phStderr,
                                fDetach, NULL );
   if( hProcess != FS_ERROR )
   {
#if defined( HB_OS_WIN )

      HB_BOOL fFinished = HB_FALSE, fBlocked;
      int iPipeCount = 0;

      if( nStdInLen == 0 && hStdin != FS_ERROR )
      {
         hb_fsClose( hStdin );
         hStdin = FS_ERROR;
      }
      if( hStdout == hStderr )
         hStderr = FS_ERROR;

      if( hStdin != FS_ERROR )
         ++iPipeCount;
      if( hStdout != FS_ERROR )
         ++iPipeCount;
      if( hStderr != FS_ERROR )
         ++iPipeCount;

      fBlocked = iPipeCount <= 1;
      if( ! fBlocked )
      {
         if( hStdin != FS_ERROR )
            hb_fsPipeUnblock( hStdin );
         if( hStdout != FS_ERROR )
            hb_fsPipeUnblock( hStdout );
         if( hStderr != FS_ERROR )
            hb_fsPipeUnblock( hStderr );
      }

      for( ;; )
      {
         DWORD dwResult, dwWait;
         HB_SIZE nLen;

         dwWait = 1000;

         if( hStdout != FS_ERROR )
         {
            if( nOutBuf == nOutSize )
            {
               if( nOutSize == 0 )
                  nOutSize = HB_STD_BUFFER_SIZE;
               else
                  nOutSize += nOutSize >> 1;
               pOutBuf = ( char * ) hb_xrealloc( pOutBuf, nOutSize + 1 );
            }
            nLen = hb_fsReadLarge( hStdout, pOutBuf + nOutBuf, nOutSize - nOutBuf );
            if( nLen > 0 )
               nOutBuf += nLen;
            else if( fBlocked )
            {
               hb_fsClose( hStdout );
               hStdout = FS_ERROR;
               --iPipeCount;
            }
            dwWait = nLen > 0 ? 0 : 10;
         }

         if( hStderr != FS_ERROR )
         {
            if( nErrBuf == nErrSize )
            {
               if( nErrSize == 0 )
                  nErrSize = HB_STD_BUFFER_SIZE;
               else
                  nErrSize += nErrSize >> 1;
               pErrBuf = ( char * ) hb_xrealloc( pErrBuf, nErrSize + 1 );
            }
            nLen = hb_fsReadLarge( hStderr, pErrBuf + nErrBuf, nErrSize - nErrBuf );
            if( nLen > 0 )
               nErrBuf += nLen;
            else if( fBlocked )
            {
               hb_fsClose( hStderr );
               hStderr = FS_ERROR;
               --iPipeCount;
            }
            if( dwWait )
               dwWait = nLen > 0 ? 0 : 10;
         }

         if( fFinished )
         {
            if( dwWait != 0 )
               break;
         }
         else if( hStdin != FS_ERROR )
         {
            nLen = ! fBlocked && nStdInLen > 4096 ? 4096 : nStdInLen;
            nLen = hb_fsWriteLarge( hStdin, pStdInBuf, nLen );
            pStdInBuf += nLen;
            nStdInLen -= nLen;
            if( nStdInLen == 0 || ( fBlocked && nLen == 0 ) )
            {
               hb_fsClose( hStdin );
               hStdin = FS_ERROR;
               --iPipeCount;
            }
            else if( dwWait )
               dwWait = nLen > 0 ? 0 : 10;
         }

         if( iPipeCount == 0 )
            dwWait = INFINITE;
         dwResult = WaitForSingleObject( ( HANDLE ) hb_fsGetOsHandle( hProcess ), dwWait );
         if( dwResult == WAIT_OBJECT_0 )
         {
            if( GetExitCodeProcess( ( HANDLE ) hb_fsGetOsHandle( hProcess ), &dwResult ) )
               iResult = ( int ) dwResult;
            else
               iResult = -2;
            fFinished = HB_TRUE;
         }
      }

      if( hStdin != FS_ERROR )
         hb_fsClose( hStdin );
      if( hStdout != FS_ERROR )
         hb_fsClose( hStdout );
      if( hStderr != FS_ERROR )
         hb_fsClose( hStderr );

      CloseHandle( ( HANDLE ) hb_fsGetOsHandle( hProcess ) );

#elif defined( HB_OS_OS2 ) || defined( HB_OS_WIN )

      HB_MAXINT nTimeOut = 0;
      int iPipeCount = 0;

      if( nStdInLen == 0 && hStdin != FS_ERROR )
      {
         hb_fsClose( hStdin );
         hStdin = FS_ERROR;
      }
      if( hStdout == hStderr )
         hStderr = FS_ERROR;

      if( hStdin != FS_ERROR )
         ++iPipeCount;
      if( hStdout != FS_ERROR )
         ++iPipeCount;
      if( hStderr != FS_ERROR )
         ++iPipeCount;

      while( iPipeCount > 0 )
      {
         HB_MAXINT nNextTOut = 10;
         HB_SIZE nLen;

         if( hStdin != FS_ERROR )
         {
            if( iPipeCount == 1 )
               nLen = hb_fsWriteLarge( hStdin, pStdInBuf, nStdInLen );
            else
               nLen = hb_fsPipeWrite( hStdin, pStdInBuf, nStdInLen, nTimeOut );
            if( nLen == ( HB_SIZE ) ( iPipeCount == 1 ? 0 : FS_ERROR ) )
               nStdInLen = 0;
            else if( nLen > 0 )
            {
               pStdInBuf += nLen;
               nStdInLen -= nLen;
               nNextTOut = 0;
            }
            if( nStdInLen == 0 )
            {
               hb_fsClose( hStdin );
               hStdin = FS_ERROR;
               --iPipeCount;
            }
         }

         if( hStdout != FS_ERROR )
         {
            if( nOutBuf == nOutSize )
            {
               if( nOutSize == 0 )
                  nOutSize = HB_STD_BUFFER_SIZE;
               else
                  nOutSize += nOutSize >> 1;
               pOutBuf = ( char * ) hb_xrealloc( pOutBuf, nOutSize + 1 );
            }
            if( iPipeCount == 1 )
               nLen = hb_fsReadLarge( hStdout, pOutBuf + nOutBuf, nOutSize - nOutBuf );
            else
               nLen = hb_fsPipeRead( hStdout, pOutBuf + nOutBuf, nOutSize - nOutBuf, nTimeOut );
            if( nLen == ( HB_SIZE ) ( iPipeCount == 1 ? 0 : FS_ERROR ) )
            {
               hb_fsClose( hStdout );
               hStdout = FS_ERROR;
               --iPipeCount;
            }
            else if( nLen > 0 )
            {
               nOutBuf += nLen;
               nNextTOut = 0;
            }
         }

         if( hStderr != FS_ERROR )
         {
            if( nErrBuf == nErrSize )
            {
               if( nErrSize == 0 )
                  nErrSize = HB_STD_BUFFER_SIZE;
               else
                  nErrSize += nErrSize >> 1;
               pErrBuf = ( char * ) hb_xrealloc( pErrBuf, nErrSize + 1 );
            }
            if( iPipeCount == 1 )
               nLen = hb_fsReadLarge( hStderr, pErrBuf + nErrBuf, nErrSize - nErrBuf );
            else
               nLen = hb_fsPipeRead( hStderr, pErrBuf + nErrBuf, nErrSize - nErrBuf, nTimeOut );
            if( nLen == ( HB_SIZE ) ( iPipeCount == 1 ? 0 : FS_ERROR ) )
            {
               hb_fsClose( hStderr );
               hStderr = FS_ERROR;
               --iPipeCount;
            }
            else if( nLen > 0 )
            {
               nErrBuf += nLen;
               nNextTOut = 0;
            }
         }

         nTimeOut = nNextTOut;
      }

      if( hStdin != FS_ERROR )
         hb_fsClose( hStdin );
      if( hStdout != FS_ERROR )
         hb_fsClose( hStdout );
      if( hStderr != FS_ERROR )
         hb_fsClose( hStderr );

      iResult = hb_fsProcessValue( hProcess, HB_TRUE );

#elif defined( HB_OS_UNIX ) && ! defined( HB_OS_SYMBIAN )

      if( nStdInLen == 0 && hStdin != FS_ERROR )
      {
         hb_fsClose( hStdin );
         hStdin = FS_ERROR;
      }
      if( hStdout == hStderr )
         hStderr = FS_ERROR;

      if( hStdin != FS_ERROR )
         hb_fsPipeUnblock( hStdin );
      if( hStdout != FS_ERROR )
         hb_fsPipeUnblock( hStdout );
      if( hStderr != FS_ERROR )
         hb_fsPipeUnblock( hStderr );

      for( ;; )
      {
         HB_BOOL fStdout, fStderr, fStdin;
         HB_SIZE nLen;

#if defined( HB_HAS_POLL )
         {
            struct pollfd fds[ 3 ];
            nfds_t nfds = 0;

            if( hStdout != FS_ERROR )
            {
               fds[ nfds ].fd = hStdout;
               fds[ nfds ].events = POLLIN;
               fds[ nfds++ ].revents = 0;
            }
            if( hStderr != FS_ERROR )
            {
               fds[ nfds ].fd = hStderr;
               fds[ nfds ].events = POLLIN;
               fds[ nfds++ ].revents = 0;
            }
            if( hStdin != FS_ERROR )
            {
               fds[ nfds ].fd = hStdin;
               fds[ nfds ].events = POLLOUT;
               fds[ nfds++ ].revents = 0;
            }
            if( nfds == 0 )
               break;

            iResult = poll( fds, nfds, -1 );
            hb_fsSetIOError( iResult >= 0, 0 );
            if( iResult == -1 && hb_fsOsError() == ( HB_ERRCODE ) EINTR &&
                hb_vmRequestQuery() == 0 )
               continue;
            else if( iResult <= 0 )
               break;

            nfds = 0;
            fStdout = fStderr = fStdin = HB_FALSE;
            if( hStdout != FS_ERROR )
            {
               if( ( fds[ nfds ].revents & POLLIN ) != 0 )
                  fStdout = HB_TRUE;
               else if( ( fds[ nfds ].revents & ( POLLHUP | POLLNVAL | POLLERR ) ) != 0 )
               {
                  hb_fsClose( hStdout );
                  hStdout = FS_ERROR;
               }
               nfds++;
            }
            if( hStderr != FS_ERROR )
            {
               if( ( fds[ nfds ].revents & POLLIN ) != 0 )
                  fStderr = HB_TRUE;
               else if( ( fds[ nfds ].revents & ( POLLHUP | POLLNVAL | POLLERR ) ) != 0 )
               {
                  hb_fsClose( hStderr );
                  hStderr = FS_ERROR;
               }
               nfds++;
            }
            if( hStdin != FS_ERROR )
            {
               if( ( fds[ nfds ].revents & POLLOUT ) != 0 )
                  fStdin = HB_TRUE;
               else if( ( fds[ nfds ].revents & ( POLLHUP | POLLNVAL | POLLERR ) ) != 0 )
               {
                  hb_fsClose( hStdin );
                  hStderr = FS_ERROR;
               }
            }
         }
#else /* ! HB_HAS_POLL */
         {
            fd_set rfds, wfds, *prfds, *pwfds;
            HB_FHANDLE fdMax;

            fdMax = 0;
            prfds = pwfds = NULL;
            if( hStdout != FS_ERROR || hStderr != FS_ERROR )
            {
               FD_ZERO( &rfds );
               if( hStdout != FS_ERROR )
               {
                  FD_SET( hStdout, &rfds );
                  if( hStdout > fdMax )
                     fdMax = hStdout;
               }
               if( hStderr != FS_ERROR )
               {
                  FD_SET( hStderr, &rfds );
                  if( hStderr > fdMax )
                     fdMax = hStderr;
               }
               prfds = &rfds;
            }
            if( hStdin != FS_ERROR )
            {
               FD_ZERO( &wfds );
               FD_SET( hStdin, &wfds );
               if( hStdin > fdMax )
                  fdMax = hStdin;
               pwfds = &wfds;
            }
            if( prfds == NULL && pwfds == NULL )
               break;

            iResult = select( fdMax + 1, prfds, pwfds, NULL, NULL );
            hb_fsSetIOError( iResult >= 0, 0 );
            if( iResult == -1 && hb_fsOsError() != ( HB_ERRCODE ) EINTR &&
                hb_vmRequestQuery() == 0 )
               continue;
            else if( iResult <= 0 )
               break;
            fStdout = hStdout != FS_ERROR && FD_ISSET( hStdout, &rfds );
            fStderr = hStderr != FS_ERROR && FD_ISSET( hStderr, &rfds );
            fStdin = hStdin != FS_ERROR && FD_ISSET( hStdin, &wfds );
         }
#endif /* ! HB_HAS_POLL */

         if( fStdout )
         {
            if( nOutBuf == nOutSize )
            {
               if( nOutSize == 0 )
                  nOutSize = HB_STD_BUFFER_SIZE;
               else
                  nOutSize += nOutSize >> 1;
               pOutBuf = ( char * ) hb_xrealloc( pOutBuf, nOutSize + 1 );
            }
            nLen = hb_fsReadLarge( hStdout, pOutBuf + nOutBuf, nOutSize - nOutBuf );
            if( nLen == 0 )
            {
               /* zero bytes read after positive Select()
                * - writing process closed the pipe
                */
               hb_fsClose( hStdout );
               hStdout = FS_ERROR;
            }
            else
               nOutBuf += nLen;
         }

         if( fStderr )
         {
            if( nErrBuf == nErrSize )
            {
               if( nErrSize == 0 )
                  nErrSize = HB_STD_BUFFER_SIZE;
               else
                  nErrSize += nErrSize >> 1;
               pErrBuf = ( char * ) hb_xrealloc( pErrBuf, nErrSize + 1 );
            }
            nLen = hb_fsReadLarge( hStderr, pErrBuf + nErrBuf, nErrSize - nErrBuf );
            if( nLen == 0 )
            {
               /* zero bytes read after positive Select()
                * - writing process closed the pipe
                */
               hb_fsClose( hStderr );
               hStderr = FS_ERROR;
            }
            else
               nErrBuf += nLen;
         }

         if( fStdin )
         {
            nLen = hb_fsWriteLarge( hStdin, pStdInBuf, nStdInLen );
            pStdInBuf += nLen;
            nStdInLen -= nLen;
            if( nStdInLen == 0 )
            {
               hb_fsClose( hStdin );
               hStdin = FS_ERROR;
            }
         }
      }

      if( hStdin != FS_ERROR )
         hb_fsClose( hStdin );
      if( hStdout != FS_ERROR )
         hb_fsClose( hStdout );
      if( hStderr != FS_ERROR )
         hb_fsClose( hStderr );

      iResult = hb_fsProcessValue( hProcess, HB_TRUE );

#else

      int iTODO;

      HB_SYMBOL_UNUSED( nStdInLen );
      HB_SYMBOL_UNUSED( nOutSize );
      HB_SYMBOL_UNUSED( nErrSize );

#endif
   }
   hb_vmLock();
}
Ejemplo n.º 2
0
int hb_fsProcessRun( const char * pszFilename,
                     const char * pStdInBuf, HB_SIZE nStdInLen,
                     char ** pStdOutPtr, HB_SIZE * pulStdOut,
                     char ** pStdErrPtr, HB_SIZE * pulStdErr,
                     HB_BOOL fDetach )
{
   HB_FHANDLE hStdin, hStdout, hStderr, *phStdin, *phStdout, *phStderr;
   char * pOutBuf, *pErrBuf;
   HB_SIZE nOutSize, nErrSize, nOutBuf, nErrBuf;
   int iResult;

   HB_TRACE( HB_TR_DEBUG, ( "hb_fsProcessRun(%s, %p, %" HB_PFS "u, %p, %p, %p, %p, %d)", pStdInBuf, pStdInBuf, nStdInLen, pStdOutPtr, pulStdOut, pStdErrPtr, pulStdErr, fDetach ) );

   nOutBuf = nErrBuf = nOutSize = nErrSize = 0;
   pOutBuf = pErrBuf = NULL;
   hStdin = hStdout = hStderr = FS_ERROR;
   phStdin = pStdInBuf ? &hStdin : NULL;
   phStdout = pStdOutPtr && pulStdOut ? &hStdout : NULL;
   phStderr = pStdErrPtr && pulStdErr ?
              ( pStdOutPtr == pStdErrPtr ? phStdout : &hStderr ) : NULL;

#if defined( HB_OS_DOS ) || defined( HB_OS_OS2 ) || defined( HB_OS_WIN_CE )
{

#if defined( HB_OS_WIN_CE )
#  define _HB_NULLHANDLE()    FS_ERROR
#elif defined( HB_OS_UNIX )
#  define _HB_NULLHANDLE()    open( "/dev/null", O_RDWR )
#else
#  define _HB_NULLHANDLE()    open( "NUL:", O_RDWR )
#endif
   char sTmpIn[ HB_PATH_MAX ];
   char sTmpOut[ HB_PATH_MAX ];
   char sTmpErr[ HB_PATH_MAX ];

   HB_SYMBOL_UNUSED( phStdin );
   HB_SYMBOL_UNUSED( nOutSize );
   HB_SYMBOL_UNUSED( nErrSize );

   sTmpIn[ 0 ] = sTmpOut[ 0 ] = sTmpErr[ 0 ] = '\0';
   if( pStdInBuf )
   {
      hStdin = hb_fsCreateTempEx( sTmpIn, NULL, NULL, NULL, FC_NORMAL );
      if( nStdInLen )
      {
         hb_fsWriteLarge( hStdin, pStdInBuf, nStdInLen );
         hb_fsSeek( hStdin, 0, FS_SET );
      }
   }
   else if( fDetach )
      hStdin = _HB_NULLHANDLE();

   if( pStdOutPtr && pulStdOut )
      hStdout = hb_fsCreateTempEx( sTmpOut, NULL, NULL, NULL, FC_NORMAL );
   else if( fDetach )
      hStdout = _HB_NULLHANDLE();

   if( pStdErrPtr && pulStdErr )
   {
      if( phStdout == phStderr )
         hStderr = hStdout;
      else
         hStderr = hb_fsCreateTempEx( sTmpErr, NULL, NULL, NULL, FC_NORMAL );
   }
   else if( fDetach )
      hStderr = _HB_NULLHANDLE();

   iResult = hb_fsProcessExec( pszFilename, hStdin, hStdout, hStderr );

   if( hStdin != FS_ERROR )
   {
      hb_fsClose( hStdin );
      if( sTmpIn[ 0 ] )
         hb_fsDelete( sTmpIn );
   }
   if( hStdout != FS_ERROR )
   {
      if( pStdOutPtr && pulStdOut )
      {
         nOutBuf = hb_fsSeek( hStdout, 0, FS_END );
         if( nOutBuf )
         {
            pOutBuf = ( char * ) hb_xgrab( nOutBuf + 1 );
            hb_fsSeek( hStdout, 0, FS_SET );
            nOutBuf = hb_fsReadLarge( hStdout, pOutBuf, nOutBuf );
         }
      }
      hb_fsClose( hStdout );
      if( sTmpOut[ 0 ] )
         hb_fsDelete( sTmpOut );
   }
   if( hStderr != FS_ERROR && hStderr != hStdout )
   {
      if( pStdErrPtr && pulStdErr )
      {
         nErrBuf = hb_fsSeek( hStderr, 0, FS_END );
         if( nErrBuf )
         {
            pErrBuf = ( char * ) hb_xgrab( nErrBuf + 1 );
            hb_fsSeek( hStderr, 0, FS_SET );
            nErrBuf = hb_fsReadLarge( hStderr, pErrBuf, nErrBuf );
         }
      }
      hb_fsClose( hStderr );
      if( sTmpErr[ 0 ] )
         hb_fsDelete( sTmpErr );
   }
}

#else
{
   HB_FHANDLE hProcess;

   hb_vmUnlock();

   iResult = -1;
   hProcess = hb_fsProcessOpen( pszFilename, phStdin, phStdout, phStderr,
                                fDetach, NULL );
   if( hProcess != FS_ERROR )
   {
#if defined( HB_OS_WIN )
      HB_BOOL fFinished = HB_FALSE;
      int iPipeCount = 0;

      if( nStdInLen == 0 && hStdin != FS_ERROR )
      {
         hb_fsClose( hStdin );
         hStdin = FS_ERROR;
      }

      if( hStdin != FS_ERROR )
         ++iPipeCount;
      if( hStdout != FS_ERROR )
         ++iPipeCount;
      if( hStderr != FS_ERROR )
         ++iPipeCount;

      if( iPipeCount > 1 )
      {
         if( hStdin != FS_ERROR )
            hb_fsPipeUnblock( hStdin );
         if( hStdout != FS_ERROR )
            hb_fsPipeUnblock( hStdout );
         if( hStderr != FS_ERROR )
            hb_fsPipeUnblock( hStderr );
      }

      for( ;; )
      {
         DWORD dwResult, dwWait;
         HB_SIZE nLen;

         dwWait = 1000;

         if( hStdout != FS_ERROR  )
         {
            if( nOutBuf == nOutSize )
            {
               nOutSize += HB_STD_BUFFER_SIZE;
               pOutBuf = ( char * ) hb_xrealloc( pOutBuf, nOutSize + 1 );
            }
            nLen = hb_fsReadLarge( hStdout, pOutBuf + nOutBuf, nOutSize - nOutBuf );
            if( nLen > 0 )
               nOutBuf += nLen;
            else if( iPipeCount == 1 )
            {
               hb_fsClose( hStdout );
               hStdout = FS_ERROR;
               iPipeCount = 0;
            }
            dwWait = nLen > 0 ? 0 : 10;
         }

         if( hStderr != FS_ERROR )
         {
            if( nErrBuf == nErrSize )
            {
               nErrSize += HB_STD_BUFFER_SIZE;
               pErrBuf = ( char * ) hb_xrealloc( pErrBuf, nErrSize + 1 );
            }
            nLen = hb_fsReadLarge( hStderr, pErrBuf + nErrBuf, nErrSize - nErrBuf );
            if( nLen > 0 )
               nErrBuf += nLen;
            else if( iPipeCount == 1 )
            {
               hb_fsClose( hStderr );
               hStderr = FS_ERROR;
               iPipeCount = 0;
            }
            if( dwWait )
               dwWait = nLen > 0 ? 0 : 10;
         }

         if( fFinished )
         {
            if( dwWait != 0 )
               break;
         }
         else if( hStdin != FS_ERROR )
         {
            nLen = hb_fsWriteLarge( hStdin, pStdInBuf, nStdInLen );
            pStdInBuf += nLen;
            nStdInLen -= nLen;
            if( nStdInLen == 0 || ( iPipeCount == 1 && nLen == 0 ) )
            {
               hb_fsClose( hStdin );
               hStdin = FS_ERROR;
               if( iPipeCount == 1 )
                  iPipeCount = 0;
            }
            else if( dwWait )
               dwWait = nLen > 0 ? 0 : 10;
         }

         if( iPipeCount == 0 )
            dwWait = INFINITE;
         dwResult = WaitForSingleObject( ( HANDLE ) hb_fsGetOsHandle( hProcess ), dwWait );
         if( dwResult == WAIT_OBJECT_0 )
         {
            if( GetExitCodeProcess( ( HANDLE ) hb_fsGetOsHandle( hProcess ), &dwResult ) )
               iResult = ( int ) dwResult;
            else
               iResult = -2;
            fFinished = HB_TRUE;
         }
      }

      if( hStdin != FS_ERROR )
         hb_fsClose( hStdin );
      if( hStdout != FS_ERROR )
         hb_fsClose( hStdout );
      if( hStderr != FS_ERROR )
         hb_fsClose( hStderr );

      CloseHandle( ( HANDLE ) hb_fsGetOsHandle( hProcess ) );

#elif defined( HB_OS_UNIX ) && ! defined( HB_OS_SYMBIAN )

      fd_set rfds, wfds, *prfds, *pwfds;
      HB_FHANDLE fdMax;
      HB_SIZE ul;
      int n;

      if( nStdInLen == 0 && hStdin != FS_ERROR )
      {
         hb_fsClose( hStdin );
         hStdin = FS_ERROR;
      }

      if( hStdin != FS_ERROR )
         hb_fsPipeUnblock( hStdin );
      if( hStdout != FS_ERROR )
         hb_fsPipeUnblock( hStdout );
      if( hStderr != FS_ERROR )
         hb_fsPipeUnblock( hStderr );

      for( ;; )
      {
         fdMax = 0;
         prfds = pwfds = NULL;
         if( hStdout != FS_ERROR || hStderr != FS_ERROR )
         {
            FD_ZERO( &rfds );
            if( hStdout != FS_ERROR )
            {
               FD_SET( hStdout, &rfds );
               if( hStdout > fdMax )
                  fdMax = hStdout;
            }
            if( hStderr != FS_ERROR )
            {
               FD_SET( hStderr, &rfds );
               if( hStderr > fdMax )
                  fdMax = hStderr;
            }
            prfds = &rfds;
         }
         if( hStdin != FS_ERROR )
         {
            FD_ZERO( &wfds );
            FD_SET( hStdin, &wfds );
            if( hStdin > fdMax )
               fdMax = hStdin;
            pwfds = &wfds;
         }
         if( prfds == NULL && pwfds == NULL )
            break;

         n = select( fdMax + 1, prfds, pwfds, NULL, NULL );
         if( n > 0 )
         {
            if( hStdout != FS_ERROR && FD_ISSET( hStdout, &rfds ) )
            {
               if( nOutBuf == nOutSize )
               {
                  nOutSize += HB_STD_BUFFER_SIZE;
                  pOutBuf = ( char * ) hb_xrealloc( pOutBuf, nOutSize + 1 );
               }
               ul = hb_fsReadLarge( hStdout, pOutBuf + nOutBuf, nOutSize - nOutBuf );
               if( ul == 0 )
               {
                  /* zero bytes read after positive Select()
                   * - writing process closed the pipe
                   */
                  hb_fsClose( hStdout );
                  hStdout = FS_ERROR;
               }
               else
                  nOutBuf += ul;
            }

            if( hStderr != FS_ERROR && FD_ISSET( hStderr, &rfds ) )
            {
               if( nErrBuf == nErrSize )
               {
                  nErrSize += HB_STD_BUFFER_SIZE;
                  pErrBuf = ( char * ) hb_xrealloc( pErrBuf, nErrSize + 1 );
               }
               ul = hb_fsReadLarge( hStderr, pErrBuf + nErrBuf, nErrSize - nErrBuf );
               if( ul == 0 )
               {
                  /* zero bytes read after positive Select()
                   * - writing process closed the pipe
                   */
                  hb_fsClose( hStderr );
                  hStderr = FS_ERROR;
               }
               else
                  nErrBuf += ul;
            }

            if( hStdin != FS_ERROR && FD_ISSET( hStdin, &wfds ) )
            {
               ul = hb_fsWriteLarge( hStdin, pStdInBuf, nStdInLen );
               pStdInBuf += ul;
               nStdInLen -= ul;
               if( nStdInLen == 0 )
               {
                  hb_fsClose( hStdin );
                  hStdin = FS_ERROR;
               }
            }
         }
         else
            break;
      }

      if( hStdin != FS_ERROR )
         hb_fsClose( hStdin );
      if( hStdout != FS_ERROR )
         hb_fsClose( hStdout );
      if( hStderr != FS_ERROR )
         hb_fsClose( hStderr );

      iResult = hb_fsProcessValue( hProcess, HB_TRUE );

#else

      int iTODO;

      HB_SYMBOL_UNUSED( nStdInLen );

#endif
      hb_vmLock();
   }
}
#endif

   if( phStdout )
   {
      *pStdOutPtr = pOutBuf;
      *pulStdOut = nOutBuf;
   }
   if( phStderr && phStdout != phStderr )
   {
      *pStdErrPtr = pErrBuf;
      *pulStdErr = nErrBuf;
   }

   return iResult;
}