Files
harbour-core/harbour/source/rtl/hbproces.c
Viktor Szakats 2832c55881 2009-07-09 23:14 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* include/hbvmpub.h
  * include/extend.api
  * include/hbwince.h
  * include/hb_io.h
  * include/hbdefs.h
  * include/hbsetup.h
  * include/hbinit.h
  * include/clipdefs.h
  * include/hbmath.h
  * include/hbzlib.h
  * include/hbregex.h
  * include/hbexprb.c
  * source/pp/hbpp.c
  * source/lang/msgrukoi.c
  * source/lang/msgzhgb.c
  * source/lang/msgruwin.c
  * source/lang/msgelwin.c
  * source/lang/msgro.c
  * source/lang/msghriso.c
  * source/lang/msgcskam.c
  * source/lang/msggl.c
  * source/lang/msges.c
  * source/lang/msgde.c
  * source/lang/msgru866.c
  * source/lang/msgcs852.c
  * source/lang/msgplmaz.c
  * source/lang/msgpliso.c
  * source/lang/msgplwin.c
  * source/lang/msgid.c
  * source/lang/msgel.c
  * source/lang/msgdewin.c
  * source/lang/msghr437.c
  * source/lang/msghr852.c
  * source/lang/msgcsiso.c
  * source/lang/msgcswin.c
  * source/lang/msgeswin.c
  * source/vm/macro.c
  * source/vm/mainwin.c
  * source/vm/maindll.c
  * source/vm/itemapi.c
  * source/vm/hvm.c
  * source/vm/cmdarg.c
  * source/vm/mainstd.c
  * source/vm/maindllp.c
  * source/vm/fm.c
  * source/vm/extrap.c
  * source/vm/thread.c
  * source/vm/main.c
  * source/vm/break.c
  * source/vm/dynlibhb.c
  * source/vm/set.c
  * source/vm/classes.c
  * source/debug/dbgtwin.prg
  * source/debug/dbgtmenu.prg
  * source/debug/dbgmenu.prg
  * source/debug/dbgthsh.prg
  * source/debug/dbgwa.prg
  * source/common/hbgete.c
  * source/common/hbver.c
  * source/common/hbprintf.c
  * source/common/hbfsapi.c
  * source/common/hbverdsp.c
  * source/common/hbwince.c
  * source/common/hbfopen.c
  * source/common/hbdate.c
  * source/macro/macroa.c
  * source/macro/macrob.c
  * source/rtl/lennum.c
  * source/rtl/gtdos/gtdos.c
  * source/rtl/setposbs.c
  * source/rtl/gtwin/gtwin.c
  * source/rtl/typefile.prg
  * source/rtl/math.c
  * source/rtl/getsys53.prg
  * source/rtl/tobject.prg
  * source/rtl/gtcrs/gtcrs.c
  * source/rtl/gtcrs/gtcrs.h
  * source/rtl/philesx.c
  * source/rtl/filehb.c
  * source/rtl/hbtoken.c
  * source/rtl/fstemp.c
  * source/rtl/ampm.c
  * source/rtl/maxrow.c
  * source/rtl/hbstrfmt.c
  * source/rtl/transfrm.c
  * source/rtl/gttone.c
  * source/rtl/datec.c
  * source/rtl/fserr.c
  * source/rtl/pushbtn.prg
  * source/rtl/memvarbl.prg
  * source/rtl/hbregexc.c
  * source/rtl/profiler.prg
  * source/rtl/hbini.prg
  * source/rtl/dbedit.prg
  * source/rtl/filesys.c
  * source/rtl/lang.c
  * source/rtl/einstv52.prg
  * source/rtl/hbbit.c
  * source/rtl/isprint.c
  * source/rtl/altd.prg
  * source/rtl/diskspac.c
  * source/rtl/console.c
  * source/rtl/gtos2/gtos2.c
  * source/rtl/adir.prg
  * source/rtl/gui.prg
  * source/rtl/hbgtcore.c
  * source/rtl/dirdrive.c
  * source/rtl/wait.prg
  * source/rtl/mlcfunc.c
  * source/rtl/scrollbr.prg
  * source/rtl/gtapiu.c
  * source/rtl/tbrowsys.prg
  * source/rtl/oemansi.c
  * source/rtl/philes53.c
  * source/rtl/color53.prg
  * source/rtl/xsavescr.c
  * source/rtl/tgetlist.prg
  * source/rtl/gtsln/mousesln.c
  * source/rtl/gtsln/kbsln.c
  * source/rtl/gtsln/gtsln.h
  * source/rtl/disksphb.c
  * source/rtl/tlabel.prg
  * source/rtl/radiogrp.prg
  * source/rtl/scrrow.c
  * source/rtl/net.c
  * source/rtl/stuff.c
  * source/rtl/checkbox.prg
  * source/rtl/filebuf.c
  * source/rtl/mtran.c
  * source/rtl/gete.c
  * source/rtl/hbproces.c
  * source/rtl/gtwvt/gtwvt.c
  * source/rtl/fssize.c
  * source/rtl/memofile.c
  * source/rtl/hbffind.c
  * source/rtl/tmenuitm.prg
  * source/rtl/gtsys.c
  * source/rtl/devoutp.prg
  * source/codepage/uckoi8.c
  * source/codepage/uckoi8u.c
  * source/codepage/cphu852s.c
  * source/codepage/cpes850c.c
  * source/codepage/cphuisos.c
  * source/codepage/ucmaz.c
  * source/codepage/cptr857.c
  * source/codepage/ucmik.c
  * source/codepage/cphr437.c
  * source/codepage/cphuwins.c
  * source/rdd/dbjoin.prg
  * source/rdd/dbnubs.c
  * source/rdd/dbfuncs.prg
  * source/rdd/dbtotal.prg
  * source/rdd/dbstrux.prg
  * source/rdd/dbsort.prg
  * source/rdd/dbfcdx/dbfcdx1.c
  * source/rdd/hbsix/sxcompr.c
  * source/compiler/hbmain.c
  * source/compiler/expropta.c
  * source/compiler/exproptb.c
  * source/compiler/fixflex.c
  * source/compiler/compi18n.c
  * source/compiler/gencobj.c
  * source/compiler/hbopt.c
  * source/compiler/hbgenerr.c
  * utils/hbtest/rt_main.h
  * utils/hbtest/rt_main.ch
  * utils/hbtest/rt_trans.prg
  * utils/hbtest/rt_misc.prg
  * utils/hbtest/rt_vars.ch
  * contrib/gtalleg/gtalleg.c
  * contrib/gtalleg/ssf.h
  * contrib/hbmysql/mysqlold.c
  * contrib/hbmysql/mysql.c
  * contrib/hbct/charlist.c
  * contrib/hbct/ctnet.c
  * contrib/hbct/charonly.c
  * contrib/hbct/ctset.c
  * contrib/hbct/ctset.h
  * contrib/hbct/cterror.ch
  * contrib/hbct/ftoc.c
  * contrib/hbct/charevod.c
  * contrib/hbct/exponent.c
  * contrib/hbct/dattime3.c
  * contrib/hbct/ct.prg
  * contrib/hbct/cursor.c
  * contrib/hbct/color.c
  * contrib/hbct/charone.c
  * contrib/hbct/numconv.prg
  * contrib/hbct/cttime.prg
  * contrib/hbct/ctstr.h
  * contrib/hbct/atnum.c
  * contrib/hbct/disk.c
  * contrib/hbct/misc1.c
  * contrib/hbct/print.c
  * contrib/xhb/hblog.ch
  * contrib/xhb/bkgtsks.c
  * contrib/xhb/wintypes.ch
  * contrib/xhb/classex.ch
  * contrib/xhb/hbcomprs.c
  * contrib/xhb/ttable.ch
  * contrib/xhb/hbcompat.ch
  * contrib/xhb/arrayblk.prg
  * contrib/xhb/hbctypes.ch
  * contrib/xhb/xhbextrn.ch
  * contrib/xhb/filestat.c
  * contrib/xhb/hblogdef.ch
  * contrib/xhb/xhbcopyf.c
  * contrib/xhb/hbserv.c
  * contrib/xhb/xhbfunc.c
  * contrib/hbodbc/odbcold.c
  * contrib/hbtpathy/telepath.ch
  * contrib/hbmzip/hbmzip.c
  * contrib/hbblat/hbblat.ch
  * contrib/hbxbp/xbpfiledialog.prg
  * contrib/hbxbp/gra.ch
  * contrib/hbxbp/xbpwindow.prg
  * contrib/hbxbp/xbp.ch
  * contrib/hbxbp/xbphtmlviewer.prg
  * contrib/hbxbp/xbptoolbar.prg
  * contrib/hbxbp/appevent.ch
  * contrib/hbxbp/xbpgeneric.prg
  * contrib/xpp/philesx.c
  * contrib/hbnf/acctyear.prg
  * contrib/hbnf/byteneg.prg
  * contrib/hbnf/isshare.prg
  * contrib/hbnf/kspeed.c
  * contrib/hbnf/prtscr.c
  * contrib/hbnf/ftshadow.c
  * contrib/hbnf/descendn.c
  * contrib/hbnf/scancode.prg
  * contrib/hbnf/vidmode.prg
  * contrib/hbnf/acctadj.prg
  * contrib/hbnf/vidcur.prg
  * contrib/hbnf/iamidle.c
  * contrib/hbnf/acctmnth.prg
  * contrib/hbnf/madd.prg
  * contrib/hbnf/fttext.c
  * contrib/hbnf/mouse1.prg
  * contrib/hbnf/settime.prg
  * contrib/hbnf/page.prg
  * contrib/hbnf/setkeys.c
  * contrib/hbnf/month.prg
  * contrib/hbnf/acctweek.prg
  * contrib/hbnf/acctqtr.prg
  * contrib/hbnf/dosver.prg
  * contrib/hbnf/metaph.prg
  * contrib/hbnf/menu1.prg
  * contrib/hbnf/byteand.prg
  * contrib/hbnf/bytexor.prg
  * contrib/hbnf/byteor.prg
  * contrib/hbnf/asum.prg
  * contrib/hbnf/wda.prg
  * contrib/hbnf/aavg.prg
  * contrib/hbnf/mouse.c
  * contrib/hbnf/setdate.prg
  * contrib/hbnf/amedian.prg
  * contrib/hbnf/blink.prg
  * contrib/hbnf/getvid.c
  * contrib/hbnf/getver.c
  * contrib/hbnf/nwuid.prg
  * contrib/hbnf/aemaxlen.prg
  * contrib/hbnf/bitset.prg
  * contrib/hbnf/nwlstat.prg
  * contrib/hbnf/tempfile.prg
  * contrib/hbnf/diskfunc.prg
  * contrib/hbnf/d2e.prg
  * contrib/hbnf/mouse2.prg
  * contrib/hbnf/firstday.prg
  * contrib/hbnf/menutonf.prg
  * contrib/hbnf/pvid.prg
  * contrib/hbnf/isbit.prg
  * contrib/hbnf/datecnfg.prg
  * contrib/hbnf/putkey.c
  * contrib/hbnf/getenvrn.c
  * contrib/hbnf/bytenot.prg
  * contrib/hbnf/aeminlen.prg
  * contrib/hbnf/year.prg
  * contrib/hbnf/ftmenuto.ch
  * contrib/hbnf/rmdir.c
  * contrib/hbnf/sysmem.prg
  * contrib/hbnf/bitclr.prg
  * contrib/hbnf/setlastk.c
  * contrib/hbnf/clrsel.prg
  * contrib/hbcurl/hbcurl.ch
  * contrib/gtwvg/gtwvg.c
  * contrib/gtwvg/wvgax.prg
  * contrib/gtwvg/gtwvg.h
  * contrib/gtwvg/wvggui.c
  * contrib/gtwvg/wvggui.h
  * contrib/gtwvg/wvgwin.c
  * contrib/gtwvg/wvgutils.c
  * contrib/gtwvg/wvgcore.c
  * contrib/gtwvg/wvgtabpg.prg
  * contrib/gtwvg/wvgsink.c
  * contrib/gtwvg/wvgwing.c
  * contrib/hbclipsm/num.c
  * contrib/hbclipsm/stack.c
  * contrib/rddads/rddads.h
  * contrib/rddads/ads1.c
  * contrib/hbfimage/fi_winfu.c
  * contrib/hbfimage/fi_wrp.c
  * contrib/hbgd/gd.ch
  * contrib/hbgd/gdchart.prg
  * contrib/hbgd/gdimage.prg
  * contrib/hbgd/gdwrp.c
  * contrib/hbmisc/nconvert.prg
  * contrib/hbmisc/stringsx.c
  * contrib/hbmisc/spd.c
  * contrib/hbmisc/stringp.prg
  * contrib/hbwin/win_prn2.c
  * contrib/hbwin/wapi_commctrl.c
  * contrib/hbwin/wapi_winbase.c
  * contrib/hbwin/wapi_winuser.c
  * contrib/hbwin/hbwinole.h
  * contrib/hbwin/win_dll.c
  * contrib/hbwin/axfunc.prg
  * contrib/hbwin/win_prn1.c
  * contrib/hbvpdf/hbvpdf.ch
  * examples/hboleold/win_ole.c
    * Formatting:
       - Removing EOL whitespaces.
       - Removing extra empty lines at EOF.
       - Adding EOL at EOF if missing.
      (except in foreign code)
2009-07-09 21:22:22 +00:00

1265 lines
34 KiB
C

/*
* $Id$
*/
/*
* Harbour Project source code:
* low level functions to create, wait and terminate processes
*
* Copyright 2009 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
* www - http://www.harbour-project.org
* based on xHarbour code by
* Copyright 2003 Giancarlo Niccolai <gian@niccolai.ws>
* www - http://www.xharbour.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#define HB_OS_WIN_USED
/* #define HB_IO_WIN_OFF */
#include "hbapi.h"
#include "hbapifs.h"
#include "hbvm.h"
#if defined( HB_OS_UNIX )
# include <unistd.h>
# include <sys/time.h>
# include <sys/types.h>
# include <sys/wait.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <signal.h>
#elif defined( HB_OS_OS2 ) || ( defined( HB_OS_WIN ) && !defined( HB_IO_WIN ) )
# include <io.h>
# include <process.h>
# include <fcntl.h>
# if defined( HB_OS_OS2 )
# include <sys/wait.h>
# endif
#elif defined( HB_OS_DOS )
# include <process.h>
# include <fcntl.h>
# if defined( __DJGPP__ )
# include <sys/stat.h>
# include <unistd.h>
# else
# include <io.h>
# endif
#endif
#if defined( HB_OS_DOS ) || defined( HB_OS_OS2 ) || defined( HB_OS_UNIX ) || \
( defined( HB_OS_WIN ) && !defined( HB_IO_WIN ) )
/* convert command to argument list using standard bourne shell encoding:
* "" and '' can be used to group parameters with blank characters,
* the escape character is '\', quoting by '' disables escape character.
*/
static char ** hb_buildArgs( const char *pszFilename )
{
const char * src;
char ** argv, * dst, cQuote = 0;
int argc = 0;
while( HB_ISSPACE( *pszFilename ) )
++pszFilename;
src = pszFilename;
while( *src )
{
#if defined( HB_OS_UNIX )
if( *src == '\\' && cQuote != '\'' )
{
if( src[ 1 ] )
++src;
}
else
#endif
if( *src == cQuote )
cQuote = 0;
else if( cQuote == 0 )
{
#if defined( HB_OS_UNIX )
if( *src == '"' || *src == '\'' )
#else
if( *src == '"' )
#endif
cQuote = *src;
else if( HB_ISSPACE( *src ) )
{
while( HB_ISSPACE( src[ 1 ] ) )
++src;
if( src[ 1 ] )
++argc;
}
}
++src;
}
dst = ( char * ) hb_xgrab( strlen( pszFilename ) + 1 );
argv = ( char ** ) hb_xgrab( ( argc + 2 ) * sizeof( char * ) );
argv[ 0 ] = dst;
argv[ argc + 1 ] = NULL;
argc = 0;
cQuote = 0;
src = pszFilename;
while( *src )
{
#if defined( HB_OS_UNIX )
if( *src == '\\' && cQuote != '\'' )
{
if( src[ 1 ] )
{
*dst++ = src[ 1 ];
++src;
}
}
else
#endif
if( *src == cQuote )
cQuote = 0;
else if( cQuote != 0 )
*dst++ = *src;
else
{
#if defined( HB_OS_UNIX )
if( *src == '"' || *src == '\'' )
#else
if( *src == '"' )
#endif
cQuote = *src;
else if( HB_ISSPACE( *src ) )
{
*dst++ = '\0';
while( HB_ISSPACE( src[ 1 ] ) )
++src;
if( src[ 1 ] )
argv[ ++argc ] = dst;
}
else
*dst++ = *src;
}
++src;
}
*dst = 0;
return argv;
}
static void hb_freeArgs( char ** argv )
{
hb_xfree( argv[ 0 ] );
hb_xfree( argv );
}
#endif
#if defined( HB_OS_DOS ) || defined( HB_OS_OS2 ) /* || defined( HB_OS_WIN_CE ) */
static int hb_fsProcessExec( const char *pszFilename,
HB_FHANDLE hStdin, HB_FHANDLE hStdout,
HB_FHANDLE hStderr )
{
int iResult = FS_ERROR;
HB_TRACE(HB_TR_DEBUG, ("hb_fsProcessExec(%s, %p, %p, %p, %d, %p)", pszFilename, ( void * ) ( HB_PTRDIFF ) hStdin, ( void * ) ( HB_PTRDIFF ) hStdout, ( void * ) ( HB_PTRDIFF ) hStderr));
#if defined( HB_IO_WIN )
PROCESS_INFORMATION pi;
STARTUPINFO si;
DWORD dwFlags = 0;
#if defined( UNICODE )
LPWSTR lpCommand = hb_mbtowc( pszFilename );
#else
char * lpCommand = hb_strdup( pszFilename );
#endif
BOOL fError;
memset( &pi, 0, sizeof( pi ) );
memset( &si, 0, sizeof( si ) );
si.cb = sizeof( si );
si.hStdInput = hStdin == FS_ERROR ? GetStdHandle( STD_INPUT_HANDLE ) : hStdin;
si.hStdOutput = hStdout == FS_ERROR ? GetStdHandle( STD_OUTPUT_HANDLE ) : hStdout;
si.hStdError = hStderr == FS_ERROR ? GetStdHandle( STD_ERROR_HANDLE ) : hStderr;
#ifdef STARTF_USESTDHANDLES
si.dwFlags = STARTF_USESTDHANDLES;
#endif
hb_vmUnlock();
fError = ! CreateProcess( NULL, /* lpAppName */
lpCommand,
NULL, /* lpProcessAttr */
NULL, /* lpThreadAttr */
TRUE, /* bInheritHandles */
dwFlags, /* dwCreationFlags */
NULL, /* lpEnvironment */
NULL, /* lpCurrentDirectory */
&si,
&pi );
hb_fsSetIOError( !fError, 0 );
if( !fError )
{
CloseHandle( pi.hThread );
if( WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_OBJECT_0 )
{
DWORD dwResult = 0;
fError = !GetExitCodeProcess( pi.hProcess, &dwResult );
iResult = !fError ? ( int ) dwResult : -2;
}
hb_fsSetIOError( !fError, 0 );
CloseHandle( pi.hProcess );
}
hb_vmLock();
hb_xfree( lpCommand );
#elif defined( HB_OS_DOS ) || defined( HB_OS_WIN ) || defined( HB_OS_OS2 ) || \
defined( HB_OS_UNIX )
int iStdIn, iStdOut, iStdErr;
char ** argv;
argv = hb_buildArgs( pszFilename );
hb_vmUnlock();
iStdIn = iStdOut = iStdErr = FS_ERROR;
if( hStdin != FS_ERROR )
{
iStdIn = dup( 0 );
dup2( hStdin, 0 );
}
if( hStdout != FS_ERROR )
{
iStdOut = dup( 1 );
dup2( hStdout, 1 );
}
if( hStderr != FS_ERROR )
{
iStdErr = dup( 2 );
dup2( hStderr, 2 );
}
#if defined( HB_OS_UNIX )
{
pid_t pid = fork();
if( pid == 0 )
{
/* close all non std* handles */
{
int iMaxFD, i;
iMaxFD = sysconf( _SC_OPEN_MAX );
if( iMaxFD < 3 )
iMaxFD = 1024;
for( i = 3; i < iMaxFD; ++i )
close( i );
}
/* reset extended process attributes */
setuid( getuid() );
setgid( getgid() );
/* execute command */
execvp( argv[ 0 ], argv );
exit(1);
}
else if( pid != -1 )
{
int iStatus;
iResult = waitpid( pid, &iStatus, 0 );
#ifdef ERESTARTSYS
if( iResult < 0 && errno != ERESTARTSYS )
#else
if( iResult < 0 )
#endif
iResult = -2;
else if( iResult == 0 )
iResult = -1;
else
iResult = WIFEXITED( iStatus ) ? WEXITSTATUS( iStatus ) : 0;
}
}
#elif defined( _MSC_VER ) || defined( __LCC__ ) || \
defined( __XCC__ ) || defined( __POCC__ )
iResult = _spawnvp( _P_WAIT, argv[ 0 ], argv );
#elif defined( __MINGW32__ )
iResult = spawnvp( P_WAIT, argv[ 0 ], ( const char * const * ) argv );
#else
iResult = spawnvp( P_WAIT, argv[ 0 ], ( char * const * ) argv );
#endif
hb_fsSetIOError( iResult >= 0, 0 );
if( iStdIn != FS_ERROR )
dup2( iStdIn, 0 );
if( iStdOut != FS_ERROR )
dup2( iStdOut, 1 );
if( iStdErr != FS_ERROR )
dup2( iStdErr, 2 );
hb_vmLock();
hb_freeArgs( argv );
#else
{
int TODO; /* TODO: for given platform */
HB_SYMBOL_UNUSED( pszFilename );
HB_SYMBOL_UNUSED( hStdin );
HB_SYMBOL_UNUSED( hStdout );
HB_SYMBOL_UNUSED( hStderr );
hb_fsSetError( ( USHORT ) FS_ERROR );
}
#endif
return iResult;
}
#endif
HB_FHANDLE hb_fsProcessOpen( const char *pszFilename,
HB_FHANDLE *phStdin, HB_FHANDLE *phStdout,
HB_FHANDLE *phStderr,
BOOL fDetach, ULONG *pulPID )
{
HB_FHANDLE hResult = FS_ERROR;
HB_TRACE(HB_TR_DEBUG, ("hb_fsProcessOpen(%s, %p, %p, %p, %d, %p)", pszFilename, phStdin, phStdout, phStderr, fDetach, pulPID));
#if defined( HB_IO_WIN )
{
#if defined( HB_OS_WIN_CE )
# define CreatePipe( hIn, hOut, sa, flags ) ( FALSE )
#endif
BOOL fError = FALSE;
HANDLE hPipes[ 6 ];
SECURITY_ATTRIBUTES sa;
int i;
for( i = 0; i < 6; ++i )
hPipes[ i ] = INVALID_HANDLE_VALUE;
memset( &sa, 0, sizeof( sa ) );
sa.nLength = sizeof( sa );
sa.bInheritHandle = TRUE;
if( phStdin != NULL )
fError = !CreatePipe( &hPipes[0], &hPipes[1], &sa, 0 );
if( !fError && phStdout != NULL )
fError = !CreatePipe( &hPipes[2], &hPipes[3], &sa, 0 );
if( !fError && phStderr != NULL )
{
if( phStdout == phStderr )
{
hPipes[4] = hPipes[2];
hPipes[5] = hPipes[3];
}
else
fError = !CreatePipe( &hPipes[4], &hPipes[5], &sa, 0 );
}
if( fError )
hb_fsSetIOError( FALSE, 0 );
else
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
DWORD dwFlags = 0;
#if defined( UNICODE )
LPWSTR lpCommand = hb_mbtowc( pszFilename );
#else
char * lpCommand = hb_strdup( pszFilename );
#endif
memset( &pi, 0, sizeof( pi ) );
memset( &si, 0, sizeof( si ) );
si.cb = sizeof( si );
#ifdef STARTF_USESTDHANDLES
si.dwFlags = STARTF_USESTDHANDLES;
#endif
if( fDetach )
{
#ifdef STARTF_USESHOWWINDOW
si.dwFlags |= STARTF_USESHOWWINDOW;
#endif
si.wShowWindow = SW_HIDE;
si.hStdInput = hPipes[ 0 ];
si.hStdOutput = hPipes[ 3 ];
si.hStdError = hPipes[ 5 ];
#ifdef DETACHED_PROCESS
dwFlags |= DETACHED_PROCESS;
#endif
}
else
{
si.hStdInput = phStdin ? hPipes[ 0 ] : GetStdHandle( STD_INPUT_HANDLE );
si.hStdOutput = phStdout ? hPipes[ 3 ] : GetStdHandle( STD_OUTPUT_HANDLE );
si.hStdError = phStderr ? hPipes[ 5 ] : GetStdHandle( STD_ERROR_HANDLE );
}
fError = ! CreateProcess( NULL, /* lpAppName */
lpCommand,
NULL, /* lpProcessAttr */
NULL, /* lpThreadAttr */
TRUE, /* bInheritHandles */
dwFlags, /* dwCreationFlags */
NULL, /* lpEnvironment */
NULL, /* lpCurrentDirectory */
&si,
&pi );
hb_fsSetIOError( !fError, 0 );
hb_xfree( lpCommand );
if( !fError )
{
if( phStdin != NULL )
{
*phStdin = ( HB_FHANDLE ) hPipes[ 1 ];
hPipes[ 1 ] = INVALID_HANDLE_VALUE;
}
if( phStdout != NULL )
{
*phStdout = ( HB_FHANDLE ) hPipes[ 2 ];
hPipes[ 2 ] = INVALID_HANDLE_VALUE;
}
if( phStderr != NULL )
{
*phStderr = ( HB_FHANDLE ) hPipes[ 4 ];
hPipes[ 4 ] = INVALID_HANDLE_VALUE;
}
if( pulPID )
*pulPID = pi.dwProcessId;
CloseHandle( pi.hThread );
hResult = ( HB_FHANDLE ) pi.hProcess;
}
}
for( i = phStdout == phStderr ? 3 : 5; i >= 0; --i )
{
if( hPipes[ i ] != INVALID_HANDLE_VALUE )
CloseHandle( hPipes[ i ] );
}
}
#elif defined( HB_OS_UNIX )
{
BOOL fError = FALSE;
HB_FHANDLE hPipeIn [ 2 ] = { FS_ERROR, FS_ERROR },
hPipeOut[ 2 ] = { FS_ERROR, FS_ERROR },
hPipeErr[ 2 ] = { FS_ERROR, FS_ERROR };
if( phStdin != NULL )
fError = pipe( hPipeIn ) != 0;
if( !fError && phStdout != NULL )
fError = pipe( hPipeOut ) != 0;
if( !fError && phStderr != NULL )
{
if( phStdout == phStderr )
{
hPipeErr[ 0 ] = hPipeOut[ 0 ];
hPipeErr[ 1 ] = hPipeOut[ 1 ];
}
else
fError = pipe( hPipeErr ) != 0;
}
if( !fError )
{
pid_t pid = fork();
if( pid == -1 )
fError = TRUE;
else if( pid != 0 ) /* parent process */
{
if( phStdin != NULL )
{
*phStdin = ( HB_FHANDLE ) hPipeIn[ 1 ];
hPipeIn[ 1 ] = FS_ERROR;
}
if( phStdout != NULL )
{
*phStdout = ( HB_FHANDLE ) hPipeOut[ 0 ];
hPipeOut[ 0 ] = FS_ERROR;
}
if( phStderr != NULL )
{
*phStderr = ( HB_FHANDLE ) hPipeErr[ 0 ];
hPipeErr[ 0 ] = FS_ERROR;
}
if( pulPID )
*pulPID = pid;
hResult = ( HB_FHANDLE ) pid;
}
else /* child process */
{
if( fDetach && ( !phStdin || !phStdout || !phStderr ) )
{
HB_FHANDLE hNull = open( "/dev/null", O_RDWR );
if( !phStdin )
dup2( hNull, 0 );
if( !phStdout )
dup2( hNull, 1 );
if( !phStderr )
dup2( hNull, 2 );
if( hNull != FS_ERROR )
close( hNull );
}
if( phStdin != NULL )
dup2( hPipeIn[ 0 ], 0 );
if( phStdout != NULL )
dup2( hPipeOut[ 1 ], 1 );
if( phStderr != NULL )
dup2( hPipeErr[ 1 ], 2 );
/* close all non std* handles */
{
int iMaxFD, i;
iMaxFD = sysconf( _SC_OPEN_MAX );
if( iMaxFD < 3 )
iMaxFD = 1024;
for( i = 3; i < iMaxFD; ++i )
close( i );
}
/* reset extended process attributes */
setuid( getuid() );
setgid( getgid() );
/* execute command */
{
#if 0
char * argv[4];
argv[0] = ( char * ) "sh";
argv[1] = ( char * ) "-c";
argv[2] = ( char * ) pszFilename;
argv[3] = ( char * ) 0;
execv( "/bin/sh", argv );
#else
char ** argv;
argv = hb_buildArgs( pszFilename );
execvp( argv[ 0 ], argv );
hb_freeArgs( argv );
#endif
exit(1);
}
}
}
hb_fsSetIOError( !fError, 0 );
if( hPipeIn[ 0 ] != FS_ERROR )
close( hPipeIn[ 0 ] );
if( hPipeIn[ 1 ] != FS_ERROR )
close( hPipeIn[ 1 ] );
if( hPipeOut[ 0 ] != FS_ERROR )
close( hPipeOut[ 0 ] );
if( hPipeOut[ 1 ] != FS_ERROR )
close( hPipeOut[ 1 ] );
if( phStdout != phStderr )
{
if( hPipeErr[ 0 ] != FS_ERROR )
close( hPipeErr[ 0 ] );
if( hPipeErr[ 1 ] != FS_ERROR )
close( hPipeErr[ 1 ] );
}
}
#elif defined( HB_OS_OS2 ) || defined( HB_OS_WIN )
{
#if defined( HB_OS_WIN )
# define pid_t int
# define _hb_pipe( e, p ) do { \
(e) = _pipe( (p), 2048, _O_BINARY ) != 0; \
} while( 0 )
#elif defined( HB_OS_OS2 )
# define _hb_pipe( e, p ) do { \
(e) = pipe( (p) ) != 0; \
if( !(e) ) \
{ \
setmode( (p)[ 0 ], O_BINARY ); \
setmode( (p)[ 1 ], O_BINARY ); \
} \
} while( 0 )
#endif
BOOL fError = FALSE;
HB_FHANDLE hPipeIn [ 2 ] = { FS_ERROR, FS_ERROR },
hPipeOut[ 2 ] = { FS_ERROR, FS_ERROR },
hPipeErr[ 2 ] = { FS_ERROR, FS_ERROR };
if( phStdin != NULL )
{
_hb_pipe( fError, hPipeIn );
}
if( !fError && phStdout != NULL )
{
_hb_pipe( fError, hPipeOut );
}
if( !fError && phStderr != NULL )
{
if( phStdout == phStderr )
{
hPipeErr[ 0 ] = hPipeOut[ 0 ];
hPipeErr[ 1 ] = hPipeOut[ 1 ];
}
else
{
_hb_pipe( fError, hPipeErr );
}
}
if( !fError )
{
int hStdIn, hStdOut, hStdErr;
char ** argv;
pid_t pid;
hStdIn = dup( 0 );
hStdOut = dup( 1 );
hStdErr = dup( 2 );
if( fDetach && ( !phStdin || !phStdout || !phStderr ) )
{
HB_FHANDLE hNull = open( "NUL:", O_RDWR );
if( !phStdin )
dup2( hNull, 0 );
if( !phStdout )
dup2( hNull, 1 );
if( !phStderr )
dup2( hNull, 2 );
if( hNull != FS_ERROR )
close( hNull );
}
if( phStdin != NULL )
dup2( hPipeIn[ 0 ], 0 );
if( phStdout != NULL )
dup2( hPipeOut[ 1 ], 1 );
if( phStderr != NULL )
dup2( hPipeErr[ 1 ], 2 );
argv = hb_buildArgs( pszFilename );
#if defined( _MSC_VER ) || defined( __LCC__ ) || \
defined( __XCC__ ) || defined( __POCC__ )
pid = _spawnvp( _P_NOWAIT, argv[ 0 ], argv );
#elif defined( __MINGW32__ )
pid = spawnvp( P_NOWAIT, argv[ 0 ], ( const char * const * ) argv );
#else
pid = spawnvp( P_NOWAIT, argv[ 0 ], ( char * const * ) argv );
#endif
hb_freeArgs( argv );
dup2( hStdIn, 0 );
dup2( hStdOut, 1 );
dup2( hStdErr, 2 );
if( pid < 0 )
fError = TRUE;
else if( pid != 0 ) /* parent process */
{
if( phStdin != NULL )
{
*phStdin = ( HB_FHANDLE ) hPipeIn[ 1 ];
hPipeIn[ 1 ] = FS_ERROR;
}
if( phStdout != NULL )
{
*phStdout = ( HB_FHANDLE ) hPipeOut[ 0 ];
hPipeOut[ 0 ] = FS_ERROR;
}
if( phStderr != NULL )
{
*phStderr = ( HB_FHANDLE ) hPipeErr[ 0 ];
hPipeErr[ 0 ] = FS_ERROR;
}
if( pulPID )
*pulPID = pid;
hResult = ( HB_FHANDLE ) pid;
}
}
hb_fsSetIOError( !fError, 0 );
if( hPipeIn[ 0 ] != FS_ERROR )
close( hPipeIn[ 0 ] );
if( hPipeIn[ 1 ] != FS_ERROR )
close( hPipeIn[ 1 ] );
if( hPipeOut[ 0 ] != FS_ERROR )
close( hPipeOut[ 0 ] );
if( hPipeOut[ 1 ] != FS_ERROR )
close( hPipeOut[ 1 ] );
if( phStdout != phStderr )
{
if( hPipeErr[ 0 ] != FS_ERROR )
close( hPipeErr[ 0 ] );
if( hPipeErr[ 1 ] != FS_ERROR )
close( hPipeErr[ 1 ] );
}
}
#else
{
int TODO; /* TODO: for given platform */
HB_SYMBOL_UNUSED( pszFilename );
HB_SYMBOL_UNUSED( phStdin );
HB_SYMBOL_UNUSED( phStdout );
HB_SYMBOL_UNUSED( phStderr );
HB_SYMBOL_UNUSED( fDetach );
HB_SYMBOL_UNUSED( pulPID );
hb_fsSetError( ( USHORT ) FS_ERROR );
}
#endif
return hResult;
}
int hb_fsProcessValue( HB_FHANDLE hProcess, BOOL fWait )
{
int iRetStatus = -1;
HB_TRACE(HB_TR_DEBUG, ("hb_fsProcessValue(%p, %d)", ( void * ) ( HB_PTRDIFF ) hProcess, fWait));
#if defined( HB_IO_WIN )
{
BOOL fError = TRUE;
DWORD dwResult;
HANDLE hProc = ( HANDLE ) hb_fsGetOsHandle( hProcess );
if( hProc )
{
hb_vmUnlock();
dwResult = WaitForSingleObject( hProc, fWait ? INFINITE : 0 );
if( dwResult == WAIT_OBJECT_0 )
{
fError = !GetExitCodeProcess( hProc, &dwResult );
iRetStatus = !fError ? ( int ) dwResult : -2;
}
hb_fsSetIOError( !fError, 0 );
if( !fError )
CloseHandle( hProc );
hb_vmLock();
}
else
hb_fsSetError( ( USHORT ) FS_ERROR );
}
#elif defined( HB_OS_UNIX ) || ( defined( HB_OS_OS2 ) && defined( __GNUC__ ) )
{
int iStatus;
pid_t pid = ( pid_t ) hProcess;
if( pid > 0 )
{
hb_vmUnlock();
iRetStatus = waitpid( pid, &iStatus, fWait ? 0 : WNOHANG );
hb_fsSetIOError( iRetStatus >= 0, 0 );
#ifdef ERESTARTSYS
if( iRetStatus < 0 && errno != ERESTARTSYS )
#else
if( iRetStatus < 0 )
#endif
iRetStatus = -2;
else if( iRetStatus == 0 )
iRetStatus = -1;
else
iRetStatus = WIFEXITED( iStatus ) ? WEXITSTATUS( iStatus ) : 0;
hb_vmLock();
}
else
hb_fsSetError( ( USHORT ) FS_ERROR );
}
#elif defined( HB_OS_OS2 ) || defined( HB_OS_WIN )
{
int iPid = ( int ) hProcess;
HB_SYMBOL_UNUSED( fWait );
if( iPid > 0 )
{
hb_vmUnlock();
#if defined( __BORLANDC__ )
iPid = cwait( &iRetStatus, iPid, 0 );
#else
iPid = _cwait( &iRetStatus, iPid, 0 );
#endif
hb_fsSetIOError( iPid > 0, 0 );
if( iPid != ( int ) hProcess )
iRetStatus = -1;
hb_vmLock();
}
else
hb_fsSetError( ( USHORT ) FS_ERROR );
}
#else
{
int TODO; /* TODO: for given platform */
HB_SYMBOL_UNUSED( hProcess );
HB_SYMBOL_UNUSED( fWait );
hb_fsSetError( ( USHORT ) FS_ERROR );
}
#endif
return iRetStatus;
}
/* Closes/kills process. The handle is still valid until you
* catch it with hb_fsProcessValue.
*/
BOOL hb_fsProcessClose( HB_FHANDLE hProcess, BOOL fGentle )
{
BOOL fResult = FALSE;
HB_TRACE(HB_TR_DEBUG, ("hb_fsProcessClose(%p, %d)", ( void * ) ( HB_PTRDIFF ) hProcess, fGentle));
#if defined( HB_IO_WIN )
{
HANDLE hProc = ( HANDLE ) hb_fsGetOsHandle( hProcess );
if( hProc )
{
if( TerminateProcess( hProc, fGentle ? 0 : 1 ) )
fResult = TRUE;
hb_fsSetIOError( fResult, 0 );
}
else
hb_fsSetError( ( USHORT ) FS_ERROR );
}
#elif defined( HB_OS_UNIX ) || ( defined( HB_OS_OS2 ) && defined( __GNUC__ ) )
{
pid_t pid = ( pid_t ) hProcess;
if( pid > 0 )
{
if( kill( pid, fGentle ? SIGTERM : SIGKILL ) == 0 )
fResult = TRUE;
hb_fsSetIOError( fResult, 0 );
}
else
hb_fsSetError( ( USHORT ) FS_ERROR );
}
#elif defined( HB_OS_WIN )
{
HANDLE hProc = OpenProcess( PROCESS_TERMINATE, FALSE, hProcess );
if( hProc )
{
if( TerminateProcess( hProc, fGentle ? 0 : 1 ) )
fResult = TRUE;
hb_fsSetIOError( fResult, 0 );
CloseHandle( hProc );
}
else
hb_fsSetError( ( USHORT ) FS_ERROR );
}
#else
{
int TODO; /* TODO: for given platform */
HB_SYMBOL_UNUSED( hProcess );
HB_SYMBOL_UNUSED( fGentle );
hb_fsSetError( ( USHORT ) FS_ERROR );
}
#endif
return fResult;
}
#define HB_STD_BUFFER_SIZE 4096
int hb_fsProcessRun( const char * pszFilename,
const char * pStdInBuf, ULONG ulStdInLen,
char ** pStdOutPtr, ULONG * pulStdOut,
char ** pStdErrPtr, ULONG * pulStdErr,
BOOL fDetach )
{
HB_FHANDLE hStdin, hStdout, hStderr, *phStdin, *phStdout, *phStderr;
char * pOutBuf, *pErrBuf;
ULONG ulOutSize, ulErrSize, ulOutBuf, ulErrBuf;
int iResult;
HB_TRACE(HB_TR_DEBUG, ("hb_fsProcessRun(%s, %p, %lu, %p, %p, %p, %p, %d)", pStdInBuf, ulStdInLen, pStdOutPtr, pulStdOut, pStdErrPtr, pulStdErr, fDetach));
ulOutBuf = ulErrBuf = ulOutSize = ulErrSize = 0;
pOutBuf = pErrBuf = NULL;
hStdin = hStdout = hStderr = FS_ERROR;
phStdin = pStdInBuf ? &hStdin : NULL;
phStdout = pStdOutPtr && pulStdOut ? &hStdout : NULL;
phStderr = pStdErrPtr && pulStdErr ? &hStderr : NULL;
#if defined( HB_OS_DOS ) || defined( HB_OS_OS2 ) /* || defined( HB_OS_WIN_CE ) */
{
#if 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 ];
sTmpIn[ 0 ] = sTmpOut[ 0 ] = sTmpErr[ 0 ] = '\0';
if( pStdInBuf )
{
hStdin = hb_fsCreateTempEx( sTmpIn, NULL, NULL, NULL, FC_NORMAL );
if( ulStdInLen )
{
hb_fsWriteLarge( hStdin, pStdInBuf, ulStdInLen );
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 )
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 )
{
ulOutBuf = hb_fsSeek( hStdout, 0, FS_END );
if( ulOutBuf )
{
pOutBuf = ( char * ) hb_xgrab( ulOutBuf + 1 );
hb_fsSeek( hStdout, 0, FS_SET );
ulOutBuf = hb_fsReadLarge( hStdout, pOutBuf, ulOutBuf );
}
}
hb_fsClose( hStdout );
if( sTmpOut[ 0 ] )
hb_fsDelete( sTmpOut );
}
if( hStderr != FS_ERROR )
{
if( pStdErrPtr && pulStdErr )
{
ulErrBuf = hb_fsSeek( hStderr, 0, FS_END );
if( ulErrBuf )
{
pErrBuf = ( char * ) hb_xgrab( ulErrBuf + 1 );
hb_fsSeek( hStderr, 0, FS_SET );
ulErrBuf = hb_fsReadLarge( hStderr, pErrBuf, ulErrBuf );
}
}
hb_fsClose( hStderr );
if( sTmpErr[ 0 ] )
hb_fsDelete( sTmpErr );
}
}
#else
{
HB_FHANDLE hProcess;
iResult = -1;
hProcess = hb_fsProcessOpen( pszFilename, phStdin, phStdout, phStderr,
fDetach, NULL );
if( hProcess != FS_ERROR )
{
#if defined( HB_IO_WIN )
DWORD dwResult, dwCount;
HANDLE lpHandles[ 4 ];
ULONG ul;
if( ulStdInLen == 0 && hStdin != FS_ERROR )
{
hb_fsClose( hStdin );
hStdin = FS_ERROR;
}
for( ;; )
{
dwCount = 0;
if( ulStdInLen && hStdin != FS_ERROR )
lpHandles[ dwCount++ ] = ( HANDLE ) hb_fsGetOsHandle( hStdin );
if( hStdout != FS_ERROR )
lpHandles[ dwCount++ ] = ( HANDLE ) hb_fsGetOsHandle( hStdout );
if( hStderr != FS_ERROR )
lpHandles[ dwCount++ ] = ( HANDLE ) hb_fsGetOsHandle( hStderr );
lpHandles[ dwCount++ ] = ( HANDLE ) hb_fsGetOsHandle( hProcess );
dwResult = WaitForMultipleObjects( dwCount, lpHandles, FALSE, INFINITE );
if( /* dwResult >= WAIT_OBJECT_0 && */ dwResult < WAIT_OBJECT_0 + dwCount )
{
if( ulStdInLen && hStdin != FS_ERROR &&
lpHandles[ dwResult ] == ( HANDLE ) hb_fsGetOsHandle( hStdin ) )
{
ul = hb_fsWriteLarge( hStdin, pStdInBuf, ulStdInLen );
pStdInBuf += ul;
ulStdInLen -= ul;
if( ulStdInLen == 0 )
{
hb_fsClose( hStdin );
hStdin = FS_ERROR;
}
}
else if( hStdout != FS_ERROR &&
lpHandles[ dwResult ] == ( HANDLE ) hb_fsGetOsHandle( hStdout ) )
{
if( ulOutBuf == ulOutSize )
{
ulOutSize += HB_STD_BUFFER_SIZE;
pOutBuf = ( char * ) hb_xrealloc( pOutBuf, ulOutSize + 1 );
}
ul = hb_fsReadLarge( hStdout, pOutBuf + ulOutBuf, ulOutSize - ulOutBuf );
if( ul == 0 )
{
hb_fsClose( hStdout );
hStdout = FS_ERROR;
}
else
ulOutBuf += ul;
}
else if( hStderr != FS_ERROR && lpHandles[ dwResult ] == ( HANDLE ) hb_fsGetOsHandle( hStderr ) )
{
if( ulErrBuf == ulErrSize )
{
ulErrSize += HB_STD_BUFFER_SIZE;
pErrBuf = ( char * ) hb_xrealloc( pErrBuf, ulErrSize + 1 );
}
ul = hb_fsReadLarge( hStderr, pErrBuf + ulErrBuf, ulErrSize - ulErrBuf );
if( ul == 0 )
{
hb_fsClose( hStderr );
hStderr = FS_ERROR;
}
else
ulErrBuf += ul;
}
else if( lpHandles[ dwResult ] == ( HANDLE ) hb_fsGetOsHandle( hProcess ) )
{
if( GetExitCodeProcess( ( HANDLE ) hb_fsGetOsHandle( hProcess ), &dwResult ) )
iResult = ( int ) dwResult;
else
iResult = -2;
break;
}
}
else
break;
}
if( hStdin != FS_ERROR )
hb_fsClose( hStdin );
if( hStdout != FS_ERROR )
hb_fsClose( hStdout );
if( hStderr != FS_ERROR )
hb_fsClose( hStderr );
#elif defined( HB_OS_UNIX )
fd_set rfds, wfds, *prfds, *pwfds;
HB_FHANDLE fdMax;
ULONG ul;
int n;
if( ulStdInLen == 0 && hStdin != FS_ERROR )
{
hb_fsClose( hStdin );
hStdin = FS_ERROR;
}
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( ulStdInLen && hStdin != FS_ERROR )
{
FD_ZERO( &wfds );
FD_SET( hStdin, &wfds );
if( hStdin > fdMax )
fdMax = hStdin;
pwfds = &wfds;
}
if( prfds == NULL && pwfds == NULL )
break;
hb_vmUnlock();
n = select( fdMax + 1, prfds, pwfds, NULL, NULL );
if( n > 0 )
{
if( ulStdInLen && hStdin != FS_ERROR && FD_ISSET( hStdin, &wfds ) )
{
ul = hb_fsWriteLarge( hStdin, pStdInBuf, ulStdInLen );
pStdInBuf += ul;
ulStdInLen -= ul;
if( ulStdInLen == 0 )
{
hb_fsClose( hStdin );
hStdin = FS_ERROR;
}
}
if( hStdout != FS_ERROR && FD_ISSET( hStdout, &rfds ) )
{
if( ulOutBuf == ulOutSize )
{
ulOutSize += HB_STD_BUFFER_SIZE;
pOutBuf = ( char * ) hb_xrealloc( pOutBuf, ulOutSize + 1 );
}
ul = hb_fsReadLarge( hStdout, pOutBuf + ulOutBuf, ulOutSize - ulOutBuf );
if( ul == 0 )
{
/* zero bytes read after positive select()
* - writing process closed the pipe
*/
hb_fsClose( hStdout );
hStdout = FS_ERROR;
}
else
ulOutBuf += ul;
}
if( hStderr != FS_ERROR && FD_ISSET( hStderr, &rfds ) )
{
if( ulErrBuf == ulErrSize )
{
ulErrSize += HB_STD_BUFFER_SIZE;
pErrBuf = ( char * ) hb_xrealloc( pErrBuf, ulErrSize + 1 );
}
ul = hb_fsReadLarge( hStderr, pErrBuf + ulErrBuf, ulErrSize - ulErrBuf );
if( ul == 0 )
{
/* zero bytes read after positive select()
* - writing process closed the pipe
*/
hb_fsClose( hStderr );
hStderr = FS_ERROR;
}
else
ulErrBuf += ul;
}
}
hb_vmLock();
}
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, TRUE );
#else
int TODO;
HB_SYMBOL_UNUSED( ulStdInLen );
#endif
}
}
#endif
if( phStdout )
{
*pStdOutPtr = pOutBuf;
*pulStdOut = ulOutBuf;
}
if( phStderr )
{
*pStdErrPtr = pErrBuf;
*pulStdErr = ulErrBuf;
}
return iResult;
}
/* temporary hack for still missing sysconf() in Watcom 1.8 */
#if defined( HB_OS_LINUX ) && defined( __WATCOMC__ )
_WCRTLINK long sysconf( int __name )
{
int iTODO;
switch( __name )
{
case _SC_OPEN_MAX:
return 1024;
case _SC_CLK_TCK:
return 100;
case /* _SC_PAGE_SIZE */ 30:
return 4096;
}
return -1;
}
#endif