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/bios/spi_device.cpp b/bios/spi_device.cpp
index a1b1f49..1af1e66 100644
--- a/bios/spi_device.cpp
+++ b/bios/spi_device.cpp
@@ -4,6 +4,7 @@
 #include "common/include/device.hpp"
 #include "common/include/host_power.hpp"
 #include "common/include/software_manager.hpp"
+#include "common/include/utils.hpp"
 
 #include <gpiod.hpp>
 #include <phosphor-logging/lg2.hpp>
@@ -273,17 +274,15 @@
         {
             if (tool == flashToolFlashrom)
             {
-                const int status =
-                    co_await SPIDevice::writeSPIFlashWithFlashrom(image,
-                                                                  image_size);
-                if (status != 0)
+                success = co_await SPIDevice::writeSPIFlashWithFlashrom(
+                    image, image_size);
+                if (!success)
                 {
                     error(
-                        "Error writing to SPI flash {CONTROLLERINDEX}:{DEVICEINDEX}, exit code {EXITCODE}",
+                        "Error writing to SPI flash {CONTROLLERINDEX}:{DEVICEINDEX}",
                         "CONTROLLERINDEX", spiControllerIndex, "DEVICEINDEX",
-                        spiDeviceIndex, "EXITCODE", status);
+                        spiDeviceIndex);
                 }
-                success = (status == 0);
             }
             else if (tool == flashToolFlashcp)
             {
@@ -318,50 +317,7 @@
     co_return success;
 }
 
-sdbusplus::async::task<int> asyncSystem(sdbusplus::async::context& ctx,
-                                        const std::string& cmd)
-{
-    int pipefd[2];
-    if (pipe(pipefd) == -1)
-    {
-        perror("pipe");
-        co_return -1;
-    }
-
-    pid_t pid = fork();
-    if (pid == -1)
-    {
-        perror("fork");
-        close(pipefd[0]);
-        close(pipefd[1]);
-        co_return -1;
-    }
-    else 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
-    {
-        close(pipefd[1]);
-
-        sdbusplus::async::fdio pipe_fdio(ctx, pipefd[0]);
-
-        co_await pipe_fdio.next();
-
-        int status;
-        waitpid(pid, &status, 0);
-        close(pipefd[0]);
-
-        co_return WEXITSTATUS(status);
-    }
-}
-
-sdbusplus::async::task<int> SPIDevice::writeSPIFlashWithFlashrom(
+sdbusplus::async::task<bool> SPIDevice::writeSPIFlashWithFlashrom(
     const uint8_t* image, size_t image_size) const
 {
     // randomize the name to enable parallel updates
@@ -424,11 +380,11 @@
 
     debug("[flashrom] running {CMD}", "CMD", cmd);
 
-    const int exitCode = co_await asyncSystem(ctx, cmd);
+    auto success = co_await asyncSystem(ctx, cmd);
 
     std::filesystem::remove(path);
 
-    co_return exitCode;
+    co_return success;
 }
 
 sdbusplus::async::task<bool> SPIDevice::writeSPIFlashWithFlashcp(
@@ -470,11 +426,11 @@
 
     debug("running {CMD}", "CMD", cmd);
 
-    const int exitCode = co_await asyncSystem(ctx, cmd);
+    auto success = co_await asyncSystem(ctx, cmd);
 
     std::filesystem::remove(path);
 
-    co_return exitCode == 0;
+    co_return success;
 }
 
 sdbusplus::async::task<bool> SPIDevice::writeSPIFlashDefault(
diff --git a/bios/spi_device.hpp b/bios/spi_device.hpp
index 25a53d1..63e7956 100644
--- a/bios/spi_device.hpp
+++ b/bios/spi_device.hpp
@@ -110,8 +110,8 @@
     // Intel Flash Descriptor
     // @param image           the component image
     // @param image_size      size of 'image'
-    // @returns               0 on success
-    sdbusplus::async::task<int> writeSPIFlashWithFlashrom(
+    // @returns               true on success
+    sdbusplus::async::task<bool> writeSPIFlashWithFlashrom(
         const uint8_t* image, size_t image_size) const;
 
     // @description preconditions:
diff --git a/common/include/utils.hpp b/common/include/utils.hpp
new file mode 100644
index 0000000..928b136
--- /dev/null
+++ b/common/include/utils.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <sdbusplus/async.hpp>
+
+/**
+ * @brief Asynchronously executes a shell command.
+ * @param ctx Async context for monitoring the pipe.
+ * @param cmd Shell command to execute.
+ * @return Task resolving to true on success (exit code 0), false otherwise.
+ */
+sdbusplus::async::task<bool> asyncSystem(sdbusplus::async::context& ctx,
+                                         const std::string& cmd);
diff --git a/common/meson.build b/common/meson.build
index 1e29ae8..8f515e1 100644
--- a/common/meson.build
+++ b/common/meson.build
@@ -9,6 +9,7 @@
     'src/software.cpp',
     'src/software_update.cpp',
     'src/host_power.cpp',
+    'src/utils.cpp',
     include_directories: ['.', 'include/', common_include],
     dependencies: [pdi_dep, phosphor_logging_dep, sdbusplus_dep, libpldm_dep],
 )
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;
+    }
+}
diff --git a/eeprom-device/eeprom_device.cpp b/eeprom-device/eeprom_device.cpp
index ca27c28..fbe65f3 100644
--- a/eeprom-device/eeprom_device.cpp
+++ b/eeprom-device/eeprom_device.cpp
@@ -1,6 +1,7 @@
 #include "eeprom_device.hpp"
 
 #include "common/include/software.hpp"
+#include "common/include/utils.hpp"
 
 #include <phosphor-logging/lg2.hpp>
 #include <sdbusplus/async.hpp>
@@ -88,55 +89,6 @@
     return lineBulks;
 }
 
-sdbusplus::async::task<int> asyncSystem(sdbusplus::async::context& ctx,
-                                        const std::string& cmd)
-{
-    int pipefd[2];
-    if (pipe(pipefd) == -1)
-    {
-        perror("pipe");
-        co_return -1;
-    }
-
-    pid_t pid = fork();
-    if (pid == -1)
-    {
-        perror("fork");
-        close(pipefd[0]);
-        close(pipefd[1]);
-        co_return -1;
-    }
-    else 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
-    {
-        close(pipefd[1]);
-
-        auto fdio = std::make_unique<sdbusplus::async::fdio>(ctx, pipefd[0]);
-        if (!fdio)
-        {
-            perror("fdio creation failed");
-            close(pipefd[0]);
-            co_return -1;
-        }
-
-        co_await fdio->next();
-
-        int status;
-        waitpid(pid, &status, 0);
-        close(pipefd[0]);
-
-        co_return WEXITSTATUS(status);
-    }
-}
-
 static std::string getDriverPath(const std::string& chipModel)
 {
     // Currently, only EEPROM chips with the model AT24 are supported.
@@ -220,13 +172,7 @@
 
     setUpdateProgress(40);
 
-    const int rc = co_await writeEEPROM(image, image_size);
-    if (rc != 0)
-    {
-        error("Error writing to EEPROM, exit code {CODE}", "CODE", rc);
-    }
-
-    bool success = (rc == 0);
+    auto success = co_await writeEEPROM(image, image_size);
 
     if (success)
     {
@@ -378,8 +324,8 @@
     return std::filesystem::exists(driverPath + "/" + i2cDeviceId);
 }
 
-sdbusplus::async::task<int> EEPROMDevice::writeEEPROM(const uint8_t* image,
-                                                      size_t image_size) const
+sdbusplus::async::task<bool> EEPROMDevice::writeEEPROM(const uint8_t* image,
+                                                       size_t image_size) const
 {
     auto eepromPath = getEEPROMPath(bus, address);
     if (eepromPath.empty())
@@ -415,11 +361,11 @@
 
     debug("Running {CMD}", "CMD", cmd);
 
-    const int exitCode = co_await asyncSystem(ctx, cmd);
+    auto success = co_await asyncSystem(ctx, cmd);
 
     std::filesystem::remove(path);
 
-    co_return exitCode;
+    co_return success;
 }
 
 sdbusplus::async::task<> EEPROMDevice::processHostStateChange()
diff --git a/eeprom-device/eeprom_device.hpp b/eeprom-device/eeprom_device.hpp
index 6e6eee5..de1fd2d 100644
--- a/eeprom-device/eeprom_device.hpp
+++ b/eeprom-device/eeprom_device.hpp
@@ -65,8 +65,8 @@
      * @param image_size    - Size of the data to write in bytes.
      * @return `true` on success, `false` otherwise.
      */
-    sdbusplus::async::task<int> writeEEPROM(const uint8_t* image,
-                                            size_t image_size) const;
+    sdbusplus::async::task<bool> writeEEPROM(const uint8_t* image,
+                                             size_t image_size) const;
     /**
      *  @brief Handle async host state change signal and updates the version.
      */