| 167 | } |
| 168 | |
| 169 | std::string ExecAndWaitForResponseText(const char* path, char* const* args) { |
| 170 | int fd[2]; |
| 171 | pipe(fd); |
| 172 | |
| 173 | pid_t pid = fork(); |
| 174 | |
| 175 | if (pid == 0) { |
| 176 | close(fd[0]); // Close read side |
| 177 | |
| 178 | // Redirect stdout to pipe |
| 179 | dup2(fd[1], STDOUT_FILENO); |
| 180 | |
| 181 | // Close stderr |
| 182 | close(STDERR_FILENO); |
| 183 | |
| 184 | // We can now close the pipe since the duplications take care of the rest |
| 185 | close(fd[1]); |
| 186 | |
| 187 | execvp(path, args); |
| 188 | _exit(-1); |
| 189 | } else { |
| 190 | close(fd[1]); // Close write side |
| 191 | |
| 192 | // Nothing larger than this |
| 193 | char Buffer[1024] {}; |
| 194 | std::string Output {}; |
| 195 | |
| 196 | // Read the pipe until it closes |
| 197 | while (size_t Size = read(fd[0], Buffer, sizeof(Buffer))) { |
| 198 | Output += std::string_view(Buffer, Size); |
| 199 | } |
| 200 | |
| 201 | int32_t Status {}; |
| 202 | while (waitpid(pid, &Status, 0) == -1 && errno == EINTR) |
| 203 | ; |
| 204 | if (WIFEXITED(Status)) { |
| 205 | // Return what we've read |
| 206 | close(fd[0]); |
| 207 | return Output; |
| 208 | } |
| 209 | } |
| 210 | |
| 211 | return {}; |
| 212 | } |
| 213 | } // namespace Exec |
| 214 | |
| 215 | namespace WorkingAppsTester { |
no test coverage detected