common: move asyncSystem() to common

asyncSystem() is shared across updaters, so moved to common.

Change-Id: I3545d34ecc1f1bf8a226d020267ae00bcf42c5f9
Signed-off-by: Kevin Tung <Kevin.Tung@quantatw.com>
diff --git a/common/src/utils.cpp b/common/src/utils.cpp
new file mode 100644
index 0000000..683ca84
--- /dev/null
+++ b/common/src/utils.cpp
@@ -0,0 +1,79 @@
+#include "common/include/utils.hpp"
+
+#include <phosphor-logging/lg2.hpp>
+
+PHOSPHOR_LOG2_USING;
+
+sdbusplus::async::task<bool> asyncSystem(sdbusplus::async::context& ctx,
+                                         const std::string& cmd)
+{
+    int pipefd[2];
+    if (pipe(pipefd) == -1)
+    {
+        error("Failed to create pipe for command: {CMD}", "CMD", cmd);
+        co_return false;
+    }
+
+    pid_t pid = fork();
+    if (pid == 0)
+    {
+        close(pipefd[0]);
+
+        int exitCode = std::system(cmd.c_str());
+        ssize_t status = write(pipefd[1], &exitCode, sizeof(exitCode));
+
+        close(pipefd[1]);
+        _exit((status == sizeof(exitCode)) ? 0 : 1);
+    }
+    else if (pid > 0)
+    {
+        close(pipefd[1]);
+
+        auto fdio = std::make_unique<sdbusplus::async::fdio>(ctx, pipefd[0]);
+
+        if (!fdio)
+        {
+            error("Failed to create fdio for command: {CMD}", "CMD", cmd);
+            close(pipefd[0]);
+            co_return false;
+        }
+
+        co_await fdio->next();
+
+        int exitCode = -1;
+        ssize_t bytesRead = read(pipefd[0], &exitCode, sizeof(exitCode));
+        close(pipefd[0]);
+
+        if (bytesRead != sizeof(exitCode))
+        {
+            error("Failed to read exit code from command {CMD}", "CMD", cmd);
+            co_return false;
+        }
+
+        int status;
+        if (waitpid(pid, &status, 0) < 0)
+        {
+            error("waitpid failed for PID {PID} for command {CMD}", "PID", pid,
+                  "CMD", cmd);
+            co_return false;
+        }
+
+        if (exitCode != 0)
+        {
+            error("Command {CMD} exited with code {CODE}", "CMD", cmd, "CODE",
+                  exitCode);
+            co_return false;
+        }
+
+        debug("{CMD} executed successfully", "CMD", cmd);
+
+        co_return true;
+    }
+    else
+    {
+        error("Fork failed for command: {CMD}", "CMD", cmd);
+        close(pipefd[0]);
+        close(pipefd[1]);
+        co_return false;
+    }
+}