diff --git a/cmdline/CTACmdMain.cpp b/cmdline/CTACmdMain.cpp index 92b88e89199312730fbbdde2b895b3f5e6c9b1aa..0d731be96975eb381022ce22d4e7aed81f26a7cc 100644 --- a/cmdline/CTACmdMain.cpp +++ b/cmdline/CTACmdMain.cpp @@ -35,6 +35,7 @@ #include <string.h> #include <unistd.h> #include <stdexcept> +#include <xrootd/XrdCl/XrdClFile.hh> /** * Returns true if --stderr is on the command-line. @@ -119,64 +120,70 @@ std::string formatCommandPath(const int argc, const char **argv) { * @return the return code */ int sendCommand(const int argc, const char **argv) { - + int rc = 0; const bool writeToStderr = stderrIsOnTheCmdLine(argc, argv); - int p[2]; - pipe(p); //Pipe to redirect std::out - int saved_stdout = dup(STDOUT_FILENO); //Saving std::out for later usage (re-redirection) - dup2(p[1], STDOUT_FILENO); //Do the actual redirection - close(p[1]); //Closing the write side of the pipe (replaced by std::out) - long flags = fcntl(p[0], F_GETFL); - flags |= O_NONBLOCK; //Setting fd as a NONBLOCKING one so that read returns zero when data is finished - fcntl(p[0], F_SETFL, flags); - //std::out is now redirected to p[0] - - XrdCl::PropertyList properties; - properties.Set("source", formatCommandPath(argc, argv)); - properties.Set("target", "-"); //destination is stdout - XrdCl::PropertyList results; - XrdCl::CopyProcess copyProcess; - - //ConnectionWindow timeout - XrdCl::Env *env = XrdCl::DefaultEnv::GetEnv(); - env->PutInt("ConnectionWindow", 3); //timeout in 3 secs if frontend server does not respond - - XrdCl::XRootDStatus status = copyProcess.AddJob(properties, &results); - if(!status.IsOK()) + const std::string cmdPath = formatCommandPath(argc, argv); + XrdCl::File xrootFile; + + // Open the xroot file reprsenting the execution of the command { - throw std::runtime_error(status.ToStr()); + const XrdCl::XRootDStatus openStatus = xrootFile.Open(cmdPath, XrdCl::OpenFlags::Read); + if(!openStatus.IsOK()) { + throw std::runtime_error(std::string("Failed to open ") + cmdPath + ": " + openStatus.GetErrorMessage()); + } } - - status = copyProcess.Prepare(); - if(!status.IsOK()) + + // The cta frontend return code is the first char of the answer { - throw std::runtime_error(status.ToStr()); + uint64_t readOffset = 0; + uint32_t bytesRead = 0; + char rc_char = '0'; + const XrdCl::XRootDStatus readStatus = xrootFile.Read(readOffset, 1, &rc_char, bytesRead); + if(!readStatus.IsOK()) { + throw std::runtime_error(std::string("Failed to read first byte from ") + cmdPath + ": " + + readStatus.GetErrorMessage()); + } + if(bytesRead != 1) { + throw std::runtime_error(std::string("Failed to read first byte from ") + cmdPath + + ": Expected to read exactly 1 byte, actually read " + std::to_string(bytesRead) + " bytes"); + } + rc = rc_char - '0'; } - - XrdCl::CopyProgressHandler copyProgressHandler; - status = copyProcess.Run(©ProgressHandler); - if(!status.IsOK()) + + // Read and print the command result { - throw std::runtime_error(status.ToStr()); + uint64_t readOffset = 1; // The first character at offset 0 has already been read + uint32_t bytesRead = 0; + do { + bytesRead = 0; + char buf[1024]; + memset(buf, 0, sizeof(buf)); + const XrdCl::XRootDStatus readStatus = xrootFile.Read(readOffset, sizeof(buf - 1), buf, bytesRead); + if(!readStatus.IsOK()) { + //throw std::runtime_error(std::string("Failed to read ") + cmdPath + ": " + readStatus.GetErrorMessage()); + throw std::runtime_error(std::string("Failed to read ") + cmdPath + ": " + readStatus.ToString()); + } + + if(bytesRead > 0) { + std::cout << buf; + + if(writeToStderr) { + std::cerr<<buf; + } + } + + readOffset += bytesRead; + } while(bytesRead > 0); } - - dup2(saved_stdout, STDOUT_FILENO); //re-redirecting std::out to the original (everything we want is in the pipe by now) - - char rc_char = '0'; - read(p[0], &rc_char, 1); //The cta frontend return code is the first char of the answer - int rc = rc_char - '0'; - char buf[1024]; - bzero(buf, sizeof(buf)); - while(read(p[0], buf, sizeof(buf)-1)>0) { //read the rest of the answer and pipe it to std::err - buf[sizeof(buf)-1]=0; - std::cout<<buf; - if(writeToStderr) { - std::cerr<<buf; + + // Close the xroot file reprsenting the execution of the command + { + const XrdCl::XRootDStatus closeStatus = xrootFile.Close(); + if(!closeStatus.IsOK()) { + throw std::runtime_error(std::string("Failed to close ") + cmdPath + ": " + closeStatus.GetErrorMessage()); } - bzero(buf, sizeof(buf)); } - close(p[0]); - + return rc; }