Add an execute_capture_output function.

This is to run a command and return its output on stdout and stderr as a
string.

Test: N/A
Bug: 137304531
Change-Id: I382f480504753cc0603d29f56919115f9a9c9b72
diff --git a/common/libs/utils/subprocess.cpp b/common/libs/utils/subprocess.cpp
index 18dbbeb..cca5e28 100644
--- a/common/libs/utils/subprocess.cpp
+++ b/common/libs/utils/subprocess.cpp
@@ -26,6 +26,9 @@
 #include <set>
 
 #include <glog/logging.h>
+
+#include "common/libs/fs/shared_buf.h"
+
 namespace {
 
 // If a redirected-to file descriptor was already closed, it's possible that
@@ -279,4 +282,34 @@
   }
   return subprocess.Wait();
 }
+
+int execute_capture_output(const std::vector<std::string>& command,
+                           std::string* output) {
+  Command cmd(command[0]);
+  for (size_t i = 1; i < command.size(); ++i) {
+    cmd.AddParameter(command[i]);
+  }
+  cvd::SharedFD pipe_read, pipe_write;
+  cvd::SharedFD::Pipe(&pipe_read, &pipe_write);
+  cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut, pipe_write);
+  cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdErr, pipe_write);
+
+  auto subprocess = cmd.Start();
+  if (!subprocess.Started()) {
+    return -1;
+  }
+  {
+    pipe_write->Close();
+    // Force the destructor to run by moving it into a smaller scope.
+    // This is necessary to close the write end of the pipe.
+    cvd::Command forceDelete = std::move(cmd);
+  }
+
+  int read = cvd::ReadAll(pipe_read, output);
+  if (read < 0) {
+    LOG(FATAL) << "Could not read from pipe in execute_capture_output";
+  }
+  return subprocess.Wait();
+}
+
 }  // namespace cvd
diff --git a/common/libs/utils/subprocess.h b/common/libs/utils/subprocess.h
index a299798..dd435ab 100644
--- a/common/libs/utils/subprocess.h
+++ b/common/libs/utils/subprocess.h
@@ -169,4 +169,8 @@
             const std::vector<std::string>& env);
 int execute(const std::vector<std::string>& command);
 
+// Like execute, but captures stdout and stderr and returns it in "output".
+int execute_capture_output(const std::vector<std::string>& command,
+                           std::string* output);
+
 }  // namespace cvd