comparison pipes.cpp @ 2:00b62a080354

fix numerous bugs
author Yasuri <yasuri@charliesmp.net>
date Sun, 13 Sep 2026 19:40:11 +0000
parents 21b543c7aa14
children
comparison
equal deleted inserted replaced
1:a17d9d25e9ea 2:00b62a080354
1 #include <iostream> 1 #include <iostream>
2 #include <unistd.h> 2 #include <unistd.h>
3 #include <spawn.h> 3 #include <spawn.h>
4 #include <cstring> 4 #include <cstring>
5 #include <cerrno>
5 #include <string> 6 #include <string>
6 #include <sys/wait.h> 7 #include <sys/wait.h>
7 #include "process.h" 8 #include "process.h"
8 extern char** environ; 9 extern char** environ;
9 std::string run_piped(const char* path, char* const argv[], const std::string& input) 10 std::string run_piped(char* const argv[], const std::string& input)
10 { 11 {
11 int status; 12 int status;
12 pid_t pid; 13 pid_t pid;
13 int pipeA[2]; 14 int pipeA[2];
14 int pipeB[2]; 15 int pipeB[2];
22 posix_spawn_file_actions_adddup2(&actions, pipeB[1], STDOUT_FILENO); 23 posix_spawn_file_actions_adddup2(&actions, pipeB[1], STDOUT_FILENO);
23 posix_spawn_file_actions_addclose(&actions, pipeA[1]); // closes write end in child 24 posix_spawn_file_actions_addclose(&actions, pipeA[1]); // closes write end in child
24 posix_spawn_file_actions_addclose(&actions, pipeB[0]); // makes sure child doesn't read its own output pipe 25 posix_spawn_file_actions_addclose(&actions, pipeB[0]); // makes sure child doesn't read its own output pipe
25 posix_spawn_file_actions_addclose(&actions, pipeA[0]); // close read fd in child 26 posix_spawn_file_actions_addclose(&actions, pipeA[0]); // close read fd in child
26 posix_spawn_file_actions_addclose(&actions, pipeB[1]); // close read fd in child, part 2 27 posix_spawn_file_actions_addclose(&actions, pipeB[1]); // close read fd in child, part 2
27 status = posix_spawn(&pid, path, &actions, NULL, const_cast<char* const*>(argv), environ); 28 status = posix_spawnp(&pid, argv[0], &actions, NULL, const_cast<char* const*>(argv), environ);
28 close(pipeA[0]); 29 close(pipeA[0]);
29 close(pipeB[1]); 30 close(pipeB[1]);
30 if (status != 0) { 31 if (status != 0) {
31 posix_spawn_file_actions_destroy(&actions); 32 posix_spawn_file_actions_destroy(&actions);
32 close(pipeA[1]); 33 close(pipeA[1]);
33 close(pipeB[0]); 34 close(pipeB[0]);
34 std::cerr << "posix_spawn failed: " << strerror(status) << std::endl; 35 std::cerr << "posix_spawnp failed for " << argv[0] << ": " << strerror(status) << std::endl;
35 return "error"; 36 return "error";
36 } 37 }
37 write(pipeA[1],input.c_str(), input.size()); 38 size_t total_written = 0;
39 while (total_written < input.size()) {
40 ssize_t n = write(pipeA[1], input.c_str() + total_written, input.size() - total_written);
41 if (n < 0) {
42 if (errno == EINTR) {
43 continue; // interrupted
44 }
45 perror("write");
46 break; // error, give up
47 }
48 total_written += n;
49 }
38 close(pipeA[1]); 50 close(pipeA[1]);
39 char buf[256]; 51 char buf[256];
40 std::string result; 52 std::string result;
41 ssize_t n; 53 ssize_t n;
42 while ((n = read(pipeB[0], buf, sizeof(buf))) > 0) { 54 while ((n = read(pipeB[0], buf, sizeof(buf))) > 0) {