blob: 2e6d1477470df8735c63b5fe4aca786f8cab177d [file] [log] [blame]
Kevin Tunga2eb9512025-05-05 18:28:56 +08001#include "common/include/utils.hpp"
2
3#include <phosphor-logging/lg2.hpp>
4
5PHOSPHOR_LOG2_USING;
6
Kevin Tungc5387272025-07-28 18:10:43 +08007sdbusplus::async::task<bool> asyncSystem(
8 sdbusplus::async::context& ctx, const std::string& cmd,
9 std::optional<std::reference_wrapper<std::string>> result)
Kevin Tunga2eb9512025-05-05 18:28:56 +080010{
Kevin Tungc5387272025-07-28 18:10:43 +080011 int exitPipefd[2];
12 int resultPipefd[2];
13
14 if (pipe(exitPipefd) == -1 || (result && pipe(resultPipefd) == -1))
Kevin Tunga2eb9512025-05-05 18:28:56 +080015 {
16 error("Failed to create pipe for command: {CMD}", "CMD", cmd);
17 co_return false;
18 }
19
20 pid_t pid = fork();
21 if (pid == 0)
22 {
Kevin Tungc5387272025-07-28 18:10:43 +080023 close(exitPipefd[0]);
24
25 if (result)
26 {
27 close(resultPipefd[0]);
28 dup2(resultPipefd[1], STDOUT_FILENO);
29 dup2(resultPipefd[1], STDERR_FILENO);
30 close(resultPipefd[1]);
31 }
Kevin Tunga2eb9512025-05-05 18:28:56 +080032
33 int exitCode = std::system(cmd.c_str());
Kevin Tungc5387272025-07-28 18:10:43 +080034 ssize_t status = write(exitPipefd[1], &exitCode, sizeof(exitCode));
Kevin Tunga2eb9512025-05-05 18:28:56 +080035
Kevin Tungc5387272025-07-28 18:10:43 +080036 close(exitPipefd[1]);
Kevin Tunga2eb9512025-05-05 18:28:56 +080037 _exit((status == sizeof(exitCode)) ? 0 : 1);
38 }
39 else if (pid > 0)
40 {
Kevin Tungc5387272025-07-28 18:10:43 +080041 close(exitPipefd[1]);
Kevin Tunga2eb9512025-05-05 18:28:56 +080042
Kevin Tungc5387272025-07-28 18:10:43 +080043 if (result)
44 {
45 close(resultPipefd[1]);
46 }
47
48 auto fdio =
49 std::make_unique<sdbusplus::async::fdio>(ctx, exitPipefd[0]);
Kevin Tunga2eb9512025-05-05 18:28:56 +080050
51 if (!fdio)
52 {
53 error("Failed to create fdio for command: {CMD}", "CMD", cmd);
Kevin Tungc5387272025-07-28 18:10:43 +080054 close(exitPipefd[0]);
Kevin Tunga2eb9512025-05-05 18:28:56 +080055 co_return false;
56 }
57
58 co_await fdio->next();
59
Kevin Tungc5387272025-07-28 18:10:43 +080060 if (result)
61 {
62 auto& resStr = result->get();
63 resStr.clear();
64 char buffer[1024];
65 ssize_t n;
66 while ((n = read(resultPipefd[0], buffer, sizeof(buffer))) > 0)
67 {
68 resStr.append(buffer, n);
69 }
70 close(resultPipefd[0]);
71 }
72
Kevin Tunga2eb9512025-05-05 18:28:56 +080073 int exitCode = -1;
Kevin Tungc5387272025-07-28 18:10:43 +080074 ssize_t bytesRead = read(exitPipefd[0], &exitCode, sizeof(exitCode));
75 close(exitPipefd[0]);
Kevin Tunga2eb9512025-05-05 18:28:56 +080076
77 if (bytesRead != sizeof(exitCode))
78 {
79 error("Failed to read exit code from command {CMD}", "CMD", cmd);
80 co_return false;
81 }
82
83 int status;
84 if (waitpid(pid, &status, 0) < 0)
85 {
86 error("waitpid failed for PID {PID} for command {CMD}", "PID", pid,
87 "CMD", cmd);
88 co_return false;
89 }
90
91 if (exitCode != 0)
92 {
93 error("Command {CMD} exited with code {CODE}", "CMD", cmd, "CODE",
94 exitCode);
95 co_return false;
96 }
97
98 debug("{CMD} executed successfully", "CMD", cmd);
99
100 co_return true;
101 }
102 else
103 {
104 error("Fork failed for command: {CMD}", "CMD", cmd);
Kevin Tungc5387272025-07-28 18:10:43 +0800105 close(exitPipefd[0]);
106 close(exitPipefd[1]);
107 if (result)
108 {
109 close(resultPipefd[0]);
110 close(resultPipefd[1]);
111 }
Kevin Tunga2eb9512025-05-05 18:28:56 +0800112 co_return false;
113 }
114}