1 #include "common/include/utils.hpp"
2
3 #include <phosphor-logging/lg2.hpp>
4
5 PHOSPHOR_LOG2_USING;
6
asyncSystem(sdbusplus::async::context & ctx,const std::string & cmd,std::optional<std::reference_wrapper<std::string>> result)7 sdbusplus::async::task<bool> asyncSystem(
8 sdbusplus::async::context& ctx, const std::string& cmd,
9 std::optional<std::reference_wrapper<std::string>> result)
10 {
11 int exitPipefd[2];
12 int resultPipefd[2];
13
14 if (pipe(exitPipefd) == -1 || (result && pipe(resultPipefd) == -1))
15 {
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 {
23 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 }
32
33 int exitCode = std::system(cmd.c_str());
34 ssize_t status = write(exitPipefd[1], &exitCode, sizeof(exitCode));
35
36 close(exitPipefd[1]);
37 _exit((status == sizeof(exitCode)) ? 0 : 1);
38 }
39 else if (pid > 0)
40 {
41 close(exitPipefd[1]);
42
43 if (result)
44 {
45 close(resultPipefd[1]);
46 }
47
48 auto fdio =
49 std::make_unique<sdbusplus::async::fdio>(ctx, exitPipefd[0]);
50
51 if (!fdio)
52 {
53 error("Failed to create fdio for command: {CMD}", "CMD", cmd);
54 close(exitPipefd[0]);
55 co_return false;
56 }
57
58 co_await fdio->next();
59
60 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
73 int exitCode = -1;
74 ssize_t bytesRead = read(exitPipefd[0], &exitCode, sizeof(exitCode));
75 close(exitPipefd[0]);
76
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);
105 close(exitPipefd[0]);
106 close(exitPipefd[1]);
107 if (result)
108 {
109 close(resultPipefd[0]);
110 close(resultPipefd[1]);
111 }
112 co_return false;
113 }
114 }
115