#include <unistd.h>
#include <sys/wait.h>
#include <stdhdrs.h>
#include <strbuf.h>
#include <error.h>
#include <errorlog.h>
#include "log.h"
#include "spawn.h"
#include "msgspawn.h"
#include "err.h"
void Spawn::SetFile( char *arg )
{
file = arg;
}
bool Spawn::SetArgs( int argc, char **argv, bool append_dash, Error *e )
{
static char dash = '-';
int i;
if( argc > MAXARGS )
{
e->Set( MsgSpawn::TooManyArgs );
return false;
}
for( i = 0; i < argc; i++ )
{
args[ i ] = *argv++;
}
if( append_dash )
{
/*
* Appending the trailing "-" character is desired.
*/
args[ i++ ] = ‐
}
args[ i ] = NULL;
return true;
}
void Spawn::SetLog( Log *alog )
{
/*
* Set the log file object that will capture
* stdout and stderr of the spawned process.
*/
log = alog;
}
char *Spawn::GetFile()
{
return file;
}
char **Spawn::GetArgs()
{
return &args[ 0 ];
}
Log *Spawn::GetLog()
{
/*
* Get the log file object that will capture
* stdout and stderr of the spawned process.
*/
return log;
}
bool Spawn::Init( int argc, char **argv, Error *e )
{
SetFile( *argv );
if( !SetArgs( argc, argv, true, e ) )
return false;
return true;
}
bool Spawn::Init( int argc, char **argv, bool append_dash, Log *alog, Error *e )
{
SetFile( *argv );
if( !SetArgs( argc, argv, append_dash, e ) )
return false;
/*
* Set the log file object.
*/
SetLog( alog );
/*
* No errors encountered.
*/
return true;
}
bool Spawn::Exec( int ifd, Error *e )
{
int pid;
Log *slog; // log file object to capture stdout and stderr
if( ( pid = fork() ) == -1 )
return syserr( "fork", GetFile(), e );
if( pid )
return true;
if( dup2( ifd, 0 ) == -1 )
return syserr( "dup2", GetFile(), e );
if( slog = GetLog() )
{
/*
* Log file object is defined.
*/
if( slog->GetName() )
{
/*
* Name of the log file is defined.
*
* Open the log file.
*/
if( !slog->Open( e ) )
return false;
/*
* Redirect stdout and stderr to the log file.
*/
if( !slog->Dup2( 1, e ) )
return false;
if( !slog->Dup2( 2, e ) )
return false;
}
}
if( execvp( GetFile(), GetArgs() ) == -1 )
return syserr( "exec", GetFile(), e );
return true;
}
bool Spawn::Wait( Error *e )
{
int status;
int rc;
if( wait( &status ) == -1 )
return syserr( "wait", GetFile(), e );
if( WIFEXITED( status ) )
{
if( rc = WEXITSTATUS( status ) )
{
e->Set( MsgSpawn::ChildFailed ) << rc;
return false;
}
}
return true;
}