annotate pipes.cpp @ 2:00b62a080354

fix numerous bugs
author Yasuri <yasuri@charliesmp.net>
date Sun, 13 Sep 2026 19:40:11 +0000
parents 21b543c7aa14
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
1 #include <iostream>
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
2 #include <unistd.h>
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
3 #include <spawn.h>
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
4 #include <cstring>
2
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
5 #include <cerrno>
0
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
6 #include <string>
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
7 #include <sys/wait.h>
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
8 #include "process.h"
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
9 extern char** environ;
2
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
10 std::string run_piped(char* const argv[], const std::string& input)
0
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
11 {
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
12 int status;
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
13 pid_t pid;
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
14 int pipeA[2];
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
15 int pipeB[2];
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
16 if (pipe(pipeA) < 0)
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
17 return "error";
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
18 if (pipe(pipeB) < 0)
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
19 return "error";
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
20 posix_spawn_file_actions_t actions;
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
21 posix_spawn_file_actions_init(&actions); // initialize actions
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
22 posix_spawn_file_actions_adddup2(&actions, pipeA[0], STDIN_FILENO);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
23 posix_spawn_file_actions_adddup2(&actions, pipeB[1], STDOUT_FILENO);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
24 posix_spawn_file_actions_addclose(&actions, pipeA[1]); // closes write end in child
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
25 posix_spawn_file_actions_addclose(&actions, pipeB[0]); // makes sure child doesn't read its own output pipe
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
26 posix_spawn_file_actions_addclose(&actions, pipeA[0]); // close read fd in child
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
27 posix_spawn_file_actions_addclose(&actions, pipeB[1]); // close read fd in child, part 2
2
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
28 status = posix_spawnp(&pid, argv[0], &actions, NULL, const_cast<char* const*>(argv), environ);
0
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
29 close(pipeA[0]);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
30 close(pipeB[1]);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
31 if (status != 0) {
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
32 posix_spawn_file_actions_destroy(&actions);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
33 close(pipeA[1]);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
34 close(pipeB[0]);
2
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
35 std::cerr << "posix_spawnp failed for " << argv[0] << ": " << strerror(status) << std::endl;
0
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
36 return "error";
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
37 }
2
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
38 size_t total_written = 0;
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
39 while (total_written < input.size()) {
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
40 ssize_t n = write(pipeA[1], input.c_str() + total_written, input.size() - total_written);
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
41 if (n < 0) {
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
42 if (errno == EINTR) {
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
43 continue; // interrupted
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
44 }
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
45 perror("write");
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
46 break; // error, give up
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
47 }
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
48 total_written += n;
00b62a080354 fix numerous bugs
Yasuri <yasuri@charliesmp.net>
parents: 0
diff changeset
49 }
0
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
50 close(pipeA[1]);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
51 char buf[256];
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
52 std::string result;
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
53 ssize_t n;
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
54 while ((n = read(pipeB[0], buf, sizeof(buf))) > 0) {
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
55 result.append(buf, n);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
56 }
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
57 close(pipeB[0]);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
58 if (waitpid(pid, &status, 0) == -1) {
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
59 posix_spawn_file_actions_destroy(&actions);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
60 close(pipeA[1]);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
61 close(pipeB[0]);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
62 perror("waitpid");
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
63 return "error";
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
64 }
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
65 posix_spawn_file_actions_destroy(&actions);
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
66 return result;
21b543c7aa14 Initial commit
Yasuri <yasuri@charliesmp.net>
parents:
diff changeset
67 }