39#undef  ZYPP_BASE_LOGGER_LOGGROUP 
   40#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::exec" 
   58      argv[2] = commandline.c_str();
 
 
   71      const char * argvp[argv.size() + 1];
 
   73      for ( 
const std::string & arg : argv )
 
   75        argvp[c] = arg.c_str();
 
 
   91      const char * argvp[argv.size() + 1];
 
   93      for ( 
const std::string & arg : argv )
 
   95        argvp[c] = arg.c_str();
 
  100      start_program( argvp, environment, stderr_disp, stderr_fd, default_locale, root.
c_str(), 
false, 
false, use_pty );
 
 
  121      start_program( argv, environment, stderr_disp, stderr_fd, default_locale, root.
c_str(), 
false, 
false, use_pty );
 
 
  126                                      const char *
const *argv_1,
 
  132      const char *argv[i + 1];
 
  134      memcpy( &argv[1], argv_1, (i - 1) * 
sizeof (
char *) );
 
 
  139                                      const char *
const *argv_1,
 
  146      const char *argv[i + 1];
 
  148      memcpy( &argv[1], argv_1, (i - 1) * 
sizeof (
char *) );
 
 
  162                                         const char * root , 
bool switch_pgid, 
bool die_with_parent , 
bool usePty )
 
  169        DBG << 
"usePty was set, forcing the ForkSpawnEngine to start external processes" << std::endl;
 
  170        _backend = std::make_unique<zyppng::ForkSpawnEngine>();
 
  177      const char * redirectStdin = 
nullptr;     
 
  178      const char * redirectStdout = 
nullptr;    
 
  179      const char * chdirTo = 
nullptr;           
 
  183        if ( root[0] == 
'\0' )
 
  187        else if ( root[0] == 
'/' && root[1] == 
'\0' )
 
  196      for ( 
bool strip = 
false; argv[0] != 
nullptr; ++argv )
 
  199        switch ( argv[0][0] )
 
  203            redirectStdin = argv[0]+1;
 
  204            if ( *redirectStdin == 
'\0' )
 
  205              redirectStdin = 
"/dev/null";
 
  210            redirectStdout = argv[0]+1;
 
  211            if ( *redirectStdout == 
'\0' )
 
  212              redirectStdout = 
"/dev/null";
 
  217            if ( argv[0][1] == 
'/' )    
 
  239        int master_tty = 0,     slave_tty = 0;          
 
  242        DBG << 
"Using ttys for communication with " << argv[0] << endl;
 
  243        if ( 
zyppng::eintrSafeCall( ::openpty, &master_tty, &slave_tty, (
char *)0, (termios *)0, (winsize *)0) != 0)
 
  252        stdoutFd = slave_tty;
 
  253        childStdinParentFd = master_tty;
 
  254        childStdoutParentFd = master_tty;
 
  258        if ( redirectStdin ) {
 
  259          stdinFd  = open( redirectStdin, O_RDONLY );
 
  262          if ( pipe (to_external) != 0 )
 
  269          stdinFd            = to_external[0];
 
  270          childStdinParentFd = to_external[1];
 
  273        if ( redirectStdout ) {
 
  274          stdoutFd = open( redirectStdout, O_WRONLY|O_CREAT|O_APPEND, 0600 );
 
  277          int from_external[2];
 
  279          if ( pipe (from_external) != 0 )
 
  286          stdoutFd = from_external[1];
 
  287          childStdoutParentFd = from_external[0];
 
  294        stderrFd = open(
"/dev/null", O_WRONLY);
 
  298        stderrFd = *stdoutFd;
 
  306        stderrFd = stderr_fd;
 
  313        _backend->setWorkingDirectory( chdirTo );
 
  315      _backend->setDieWithParent( die_with_parent );
 
  316      _backend->setSwitchPgid( switch_pgid );
 
  317      _backend->setEnvironment( environment );
 
  318      _backend->setUseDefaultLocale( default_locale );
 
  320      if ( 
_backend->start( argv, stdinFd, stdoutFd, stderrFd ) ) {
 
  321        bool connected = 
true;
 
  322        if ( childStdoutParentFd != -1 ) {
 
  323          inputfile = fdopen( childStdoutParentFd, 
"r" );
 
  329        if ( childStdinParentFd != -1 ) {
 
  330          outputfile = fdopen( childStdinParentFd, 
"w" );
 
  338            ERR << 
"Cannot create streams to external program " << argv[0] << endl;
 
 
  347    bool ExternalProgram::waitForExit(std::optional<uint64_t> timeout)
 
  353      return _backend->waitForExit( timeout );
 
  360        ExternalDataSource::close();
 
  379            rfd.fd = inputfileFd;
 
  380            rfd.events =  G_IO_IN | G_IO_HUP | G_IO_ERR;
 
  385            gint timeout = delay < 0 ? 1000 : delay*100;
 
  386            if ( delay >= 0 && ++delay > 9 )
 
  392              ERR << 
"select error: " << strerror(errno) << endl;
 
  420      ExternalDataSource::close();
 
 
  430          ERR << 
"Failed to kill PID " << 
_backend->pid() << 
" with error: " << 
Errno() << std::endl;
 
 
  443          ERR << 
"Failed to kill PID " << 
_backend->pid() << 
" with error: " << 
Errno() << std::endl;
 
 
  467        static std::string empty;
 
 
  476        static std::string empty;
 
 
  508        ::pipe2( 
_fds, O_NONBLOCK );
 
  511        ::fcntl(
_fds[
R], F_SETFD, O_NONBLOCK );
 
  512        ::fcntl(
_fds[
W], F_SETFD, O_NONBLOCK );
 
 
  529      if ( delim_r && ! 
_buffer.empty() )
 
  532        std::string::size_type pos( 
_buffer.find( delim_r ) );
 
  533        if ( pos != std::string::npos )
 
  535          retval_r = 
_buffer.substr( 0, returnDelim_r ? pos+1 : pos );
 
  545          if ( ch != delim_r || ! delim_r )
 
  560        else if ( errno != EINTR )
 
 
void resetDispose()
Set no dispose function.
Convenience errno wrapper.
bool stderrGetUpTo(std::string &retval_r, const char delim_r, bool returnDelim_r=false)
Read data up to delim_r from stderr (nonblocking).
ExternalProgram()
Start an external program by giving the arguments as an arry of char *pointers.
int close() override
Wait for the progamm to complete.
const std::string & command() const
The command we're executing.
std::ostream & operator>>(std::ostream &out_r)
Redirect all command output to an ostream.
void start_program(const char *const *argv, const Environment &environment, Stderr_Disposition stderr_disp=Normal_Stderr, int stderr_fd=-1, bool default_locale=false, const char *root=NULL, bool switch_pgid=false, bool die_with_parent=false, bool usePty=false)
std::vector< std::string > Arguments
~ExternalProgram() override
static void renumber_fd(int origfd, int newfd)
origfd will be accessible as newfd and closed (unless they were equal)
std::map< std::string, std::string > Environment
For passing additional environment variables to set.
bool kill()
Kill the program.
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
bool running()
Return whether program is running.
Stderr_Disposition
Define symbols for different policies on the handling of stderr.
std::unique_ptr< zyppng::AbstractSpawnEngine > _backend
void setBlocking(bool mode)
Set the blocking mode of the input stream.
FILE * inputFile() const
Return the input stream.
std::string receiveLine()
Read one line from the input stream.
const char * c_str() const
String representation.
static std::unique_ptr< zyppng::AbstractSpawnEngine > createDefaultEngine()
void setUsePty(const bool set=true)
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Easy-to use interface to the ZYPP dependency resolver.
auto eintrSafeCall(Fun &&function, Args &&... args)
void renumberFd(int origfd, int newfd)
AutoDispose<int> calling close