1 #include "common/include/utils.hpp" 2 3 #include <phosphor-logging/lg2.hpp> 4 5 PHOSPHOR_LOG2_USING; 6 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