xref: /openbmc/phosphor-bmc-code-mgmt/common/src/utils.cpp (revision c538727d70f3673771f18e559d7ecab203abf6d3)
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