Repository navigation
Expand file tree
/
Copy pathpipe.cpp
More file actions
120 lines (103 loc) · 2.95 KB
/
Copy pathpipe.cpp
File metadata and controls
120 lines (103 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "headers.h"
// Execute cmd1 | cmd2 | ... | cmdN. All stages run concurrently, connected by
// pipes, and the shell waits for every stage before returning.
void executePipes(vector<string> args)
{
// Collect the individual command strings (drop the "|" separators).
vector<string> commands;
for (const string &a : args)
if (a != "|")
{
string c = a;
size_t s = c.find_first_not_of(" \t");
size_t e = c.find_last_not_of(" \t");
if (s != string::npos)
commands.push_back(c.substr(s, e - s + 1));
}
if (commands.empty())
return;
int prevRead = -1; // read end of the previous pipe
vector<pid_t> children;
for (size_t i = 0; i < commands.size(); ++i)
{
bool last = (i + 1 == commands.size());
int fds[2] = {-1, -1};
if (!last && pipe(fds) == -1)
{
perror("pipe");
break;
}
const string &command = commands[i];
bool hasRedirection =
command.find('>') != string::npos || command.find('<') != string::npos;
vector<string> tokens =
hasRedirection ? tokenizeForRedirection(command) : tokenize(command);
if (tokens.empty())
{
if (!last)
{
close(fds[0]);
close(fds[1]);
}
continue;
}
pid_t pid = fork();
if (pid == -1)
{
perror("fork");
if (!last)
{
close(fds[0]);
close(fds[1]);
}
break;
}
if (pid == 0)
{
signal(SIGINT, SIG_DFL);
signal(SIGTSTP, SIG_DFL);
if (prevRead != -1)
{
dup2(prevRead, STDIN_FILENO);
close(prevRead);
}
if (!last)
{
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
close(fds[1]);
}
if (hasRedirection)
{
redirection(tokens);
_exit(0);
}
char **argv = new char *[tokens.size() + 1];
for (size_t k = 0; k < tokens.size(); ++k)
{
argv[k] = new char[tokens[k].size() + 1];
strcpy(argv[k], tokens[k].c_str());
}
argv[tokens.size()] = nullptr;
execvp(argv[0], argv);
cerr << tokens[0] << ": command not found" << endl;
_exit(127);
}
children.push_back(pid);
if (prevRead != -1)
close(prevRead);
if (!last)
{
close(fds[1]);
prevRead = fds[0];
}
}
if (prevRead != -1)
close(prevRead);
for (pid_t pid : children)
{
int status = 0;
while (waitpid(pid, &status, 0) == -1 && errno == EINTR)
;
}
}