/* * Copyright (C) 2007-2008 Xagasoft, All rights reserved. * * This file is part of the libbu++ library and is released under the * terms of the license contained in the file LICENSE. */ #include "process.h" #include #include #include #include #include #include #include Bu::Process::Process( const char *sName, char *const argv[] ) : iPid( 0 ) { gexec( sName, argv ); } Bu::Process::Process( const char *sName, const char *argv, ...) : iPid( 0 ) { int iCnt = 0; va_list ap; va_start( ap, argv ); for(; va_arg( ap, const char *); iCnt++ ) { } va_end( ap ); char const **list = new char const *[iCnt+2]; va_start( ap, argv ); list[0] = argv; for( int j = 1; j <= iCnt; j++ ) { list[j] = va_arg( ap, const char *); } list[iCnt+1] = NULL; va_end( ap ); gexec( sName, (char *const *)list ); delete[] list; } Bu::Process::~Process() { close(); } void Bu::Process::gexec( const char *sName, char *const argv[] ) { int iaStdIn[2]; int iaStdOut[2]; // int iaStdErr[2]; pipe( iaStdIn ); pipe( iaStdOut ); // pipe( iaStdErr ); iStdIn = iaStdIn[1]; iStdOut = iaStdOut[0]; // iStdErr = iaStdErr[0]; // fcntl( iStdOut, F_SETFL, fcntl( iStdOut, F_GETFL, 0 )|O_NONBLOCK ); iPid = fork(); if( iPid == 0 ) { ::close( iaStdIn[1] ); ::close( iaStdOut[0] ); // ::close( iaStdErr[0] ); dup2( iaStdIn[0], 0 ); dup2( iaStdOut[1], 1 ); // dup2( iaStdErr[1], 2 ); execvp( sName, argv ); throw Bu::ExceptionBase("Hey, execvp failed!"); } ::close( iaStdIn[0] ); ::close( iaStdOut[1] ); // ::close( iaStdErr[1] ); } void Bu::Process::close() { if( iPid ) { ::close( iStdIn ); ::close( iStdOut ); int status; waitpid( iPid, &status, 0 ); iPid = 0; } } size_t Bu::Process::read( void *pBuf, size_t nBytes ) { return TEMP_FAILURE_RETRY( ::read( iStdOut, pBuf, nBytes ) ); /* size_t iTotal = 0; for(;;) { size_t iRet = ::read( iStdOut, (char *)pBuf+iTotal, nBytes-iTotal ); if( iRet == 0 ) return iTotal; iTotal += iRet; if( iTotal == nBytes ) return iTotal; } */ /* size_t iTotal = 0; fd_set rfs; FD_ZERO( &rfs ); for(;;) { if( waitpid( iPid, NULL, WNOHANG ) ) { printf("!!!wait failed!\n"); size_t iRet = ::read( iStdOut, (char *)pBuf+iTotal, nBytes-iTotal ); iTotal += iRet; return iTotal; } FD_SET( iStdOut, &rfs ); select( iStdOut+1, &rfs, NULL, &rfs, NULL ); size_t iRet = ::read( iStdOut, (char *)pBuf+iTotal, nBytes-iTotal ); printf("--read=%d / %d--\n", iRet, iTotal+iRet ); iTotal += iRet; if( iTotal == nBytes ) return iTotal; } */ } size_t Bu::Process::readErr( void *pBuf, size_t nBytes ) { return ::read( iStdErr, pBuf, nBytes ); } size_t Bu::Process::write( const void *pBuf, size_t nBytes ) { return TEMP_FAILURE_RETRY( ::write( iStdIn, pBuf, nBytes ) ); } long Bu::Process::tell() { return 0; } void Bu::Process::seek( long ) { } void Bu::Process::setPos( long ) { } void Bu::Process::setPosEnd( long ) { } bool Bu::Process::isEos() { return false; } bool Bu::Process::isOpen() { return true; } void Bu::Process::flush() { } bool Bu::Process::canRead() { return true; } bool Bu::Process::canWrite() { return true; } bool Bu::Process::isReadable() { return true; } bool Bu::Process::isWritable() { return true; } bool Bu::Process::isSeekable() { return false; } bool Bu::Process::isBlocking() { return true; } void Bu::Process::setBlocking( bool bBlocking ) { if( bBlocking ) fcntl( iStdOut, F_SETFL, fcntl( iStdOut, F_GETFL, 0 )&(~O_NONBLOCK) ); else fcntl( iStdOut, F_SETFL, fcntl( iStdOut, F_GETFL, 0 )|O_NONBLOCK ); }