1a2eb951fSKevin Tung #include "common/include/utils.hpp"
2a2eb951fSKevin Tung
3a2eb951fSKevin Tung #include <phosphor-logging/lg2.hpp>
4a2eb951fSKevin Tung
5a2eb951fSKevin Tung PHOSPHOR_LOG2_USING;
6a2eb951fSKevin Tung
asyncSystem(sdbusplus::async::context & ctx,const std::string & cmd,std::optional<std::reference_wrapper<std::string>> result)7*c538727dSKevin Tung sdbusplus::async::task<bool> asyncSystem(
8*c538727dSKevin Tung sdbusplus::async::context& ctx, const std::string& cmd,
9*c538727dSKevin Tung std::optional<std::reference_wrapper<std::string>> result)
10a2eb951fSKevin Tung {
11*c538727dSKevin Tung int exitPipefd[2];
12*c538727dSKevin Tung int resultPipefd[2];
13*c538727dSKevin Tung
14*c538727dSKevin Tung if (pipe(exitPipefd) == -1 || (result && pipe(resultPipefd) == -1))
15a2eb951fSKevin Tung {
16a2eb951fSKevin Tung error("Failed to create pipe for command: {CMD}", "CMD", cmd);
17a2eb951fSKevin Tung co_return false;
18a2eb951fSKevin Tung }
19a2eb951fSKevin Tung
20a2eb951fSKevin Tung pid_t pid = fork();
21a2eb951fSKevin Tung if (pid == 0)
22a2eb951fSKevin Tung {
23*c538727dSKevin Tung close(exitPipefd[0]);
24*c538727dSKevin Tung
25*c538727dSKevin Tung if (result)
26*c538727dSKevin Tung {
27*c538727dSKevin Tung close(resultPipefd[0]);
28*c538727dSKevin Tung dup2(resultPipefd[1], STDOUT_FILENO);
29*c538727dSKevin Tung dup2(resultPipefd[1], STDERR_FILENO);
30*c538727dSKevin Tung close(resultPipefd[1]);
31*c538727dSKevin Tung }
32a2eb951fSKevin Tung
33a2eb951fSKevin Tung int exitCode = std::system(cmd.c_str());
34*c538727dSKevin Tung ssize_t status = write(exitPipefd[1], &exitCode, sizeof(exitCode));
35a2eb951fSKevin Tung
36*c538727dSKevin Tung close(exitPipefd[1]);
37a2eb951fSKevin Tung _exit((status == sizeof(exitCode)) ? 0 : 1);
38a2eb951fSKevin Tung }
39a2eb951fSKevin Tung else if (pid > 0)
40a2eb951fSKevin Tung {
41*c538727dSKevin Tung close(exitPipefd[1]);
42a2eb951fSKevin Tung
43*c538727dSKevin Tung if (result)
44*c538727dSKevin Tung {
45*c538727dSKevin Tung close(resultPipefd[1]);
46*c538727dSKevin Tung }
47*c538727dSKevin Tung
48*c538727dSKevin Tung auto fdio =
49*c538727dSKevin Tung std::make_unique<sdbusplus::async::fdio>(ctx, exitPipefd[0]);
50a2eb951fSKevin Tung
51a2eb951fSKevin Tung if (!fdio)
52a2eb951fSKevin Tung {
53a2eb951fSKevin Tung error("Failed to create fdio for command: {CMD}", "CMD", cmd);
54*c538727dSKevin Tung close(exitPipefd[0]);
55a2eb951fSKevin Tung co_return false;
56a2eb951fSKevin Tung }
57a2eb951fSKevin Tung
58a2eb951fSKevin Tung co_await fdio->next();
59a2eb951fSKevin Tung
60*c538727dSKevin Tung if (result)
61*c538727dSKevin Tung {
62*c538727dSKevin Tung auto& resStr = result->get();
63*c538727dSKevin Tung resStr.clear();
64*c538727dSKevin Tung char buffer[1024];
65*c538727dSKevin Tung ssize_t n;
66*c538727dSKevin Tung while ((n = read(resultPipefd[0], buffer, sizeof(buffer))) > 0)
67*c538727dSKevin Tung {
68*c538727dSKevin Tung resStr.append(buffer, n);
69*c538727dSKevin Tung }
70*c538727dSKevin Tung close(resultPipefd[0]);
71*c538727dSKevin Tung }
72*c538727dSKevin Tung
73a2eb951fSKevin Tung int exitCode = -1;
74*c538727dSKevin Tung ssize_t bytesRead = read(exitPipefd[0], &exitCode, sizeof(exitCode));
75*c538727dSKevin Tung close(exitPipefd[0]);
76a2eb951fSKevin Tung
77a2eb951fSKevin Tung if (bytesRead != sizeof(exitCode))
78a2eb951fSKevin Tung {
79a2eb951fSKevin Tung error("Failed to read exit code from command {CMD}", "CMD", cmd);
80a2eb951fSKevin Tung co_return false;
81a2eb951fSKevin Tung }
82a2eb951fSKevin Tung
83a2eb951fSKevin Tung int status;
84a2eb951fSKevin Tung if (waitpid(pid, &status, 0) < 0)
85a2eb951fSKevin Tung {
86a2eb951fSKevin Tung error("waitpid failed for PID {PID} for command {CMD}", "PID", pid,
87a2eb951fSKevin Tung "CMD", cmd);
88a2eb951fSKevin Tung co_return false;
89a2eb951fSKevin Tung }
90a2eb951fSKevin Tung
91a2eb951fSKevin Tung if (exitCode != 0)
92a2eb951fSKevin Tung {
93a2eb951fSKevin Tung error("Command {CMD} exited with code {CODE}", "CMD", cmd, "CODE",
94a2eb951fSKevin Tung exitCode);
95a2eb951fSKevin Tung co_return false;
96a2eb951fSKevin Tung }
97a2eb951fSKevin Tung
98a2eb951fSKevin Tung debug("{CMD} executed successfully", "CMD", cmd);
99a2eb951fSKevin Tung
100a2eb951fSKevin Tung co_return true;
101a2eb951fSKevin Tung }
102a2eb951fSKevin Tung else
103a2eb951fSKevin Tung {
104a2eb951fSKevin Tung error("Fork failed for command: {CMD}", "CMD", cmd);
105*c538727dSKevin Tung close(exitPipefd[0]);
106*c538727dSKevin Tung close(exitPipefd[1]);
107*c538727dSKevin Tung if (result)
108*c538727dSKevin Tung {
109*c538727dSKevin Tung close(resultPipefd[0]);
110*c538727dSKevin Tung close(resultPipefd[1]);
111*c538727dSKevin Tung }
112a2eb951fSKevin Tung co_return false;
113a2eb951fSKevin Tung }
114a2eb951fSKevin Tung }
115