commit 539e3e7517fc4138a64aeaa3caf90cc8818cd677
parent 96e8d55747cc8e0e1b0082464be2ca874567976b
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Wed, 17 Aug 2022 23:48:19 +0100
hush: Add pipelining
Diffstat:
M | src/hush.cpp | | | 102 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
1 file changed, 72 insertions(+), 30 deletions(-)
diff --git a/src/hush.cpp b/src/hush.cpp
@@ -10,6 +10,16 @@
using namespace std;
+struct fifo
+{
+ int read, write;
+
+ operator int*()
+ {
+ return &read;
+ }
+};
+
void show_clear_warn(char const* msg)
{
if (errno)
@@ -56,42 +66,74 @@ int main(int, char**)
if (!getline(cin, buf))
break;
- istringstream is(buf);
- vector<string> args;
- while (getline(is, buf, ' '))
- args.push_back(buf);
+ istringstream ip(buf);
+ vector<string> pipelines;
- if (args.empty())
- {
- cout << '\n';
- continue;
- }
- string arg0 = args.front();
- std::vector<char*> argp;
- for (auto& a : args)
- {
- a.push_back('\0');
- argp.push_back(a.data());
- }
+ while (getline(ip, buf, '|'))
+ pipelines.push_back(buf);
- if (intrinsics.contains(arg0))
- {
- intrinsics[arg0](argp);
- continue;
- }
- argp.push_back(nullptr);
+ fifo f;
- if (fork())
- {
- int status;
- wait(&status);
- if (WEXITSTATUS(status))
- std::cout << "\nResult: " << WEXITSTATUS(status) << '\n';
- } else
+ for (unsigned i = 0; i < pipelines.size(); ++i)
{
+ int in;
+ bool make_pipe = i+1 < pipelines.size();
+ if (i)
+ in = f.read;
+
+ if (make_pipe)
+ pipe(f);
+
+ if (fork())
+ {
+ if (make_pipe)
+ close(f.write);
+ if (i)
+ close(in);
+
+ continue;
+ }
+
+ if (make_pipe)
+ {
+ dup2(f.write, STDOUT_FILENO);
+ close(f.write);
+ }
+
+ if (i)
+ {
+ dup2(in, STDIN_FILENO);
+ close(in);
+ }
+
+ istringstream is(pipelines[i]);
+ vector<string> args;
+ while (is.peek() == ' ')
+ is.get();
+ while (getline(is, buf, ' '))
+ args.push_back(buf);
+
+ if (args.empty())
+ err(1, "empty command?");
+
+
+ string arg0 = args.front();
+ std::vector<char*> argp;
+ for (auto& a : args)
+ {
+ a.push_back('\0');
+ argp.push_back(a.data());
+ }
+
+ if (intrinsics.contains(arg0))
+ exit(intrinsics[arg0](argp));
+
+ argp.push_back(nullptr);
execvp(argp[0], argp.data());
- err(66, "execv");
+ err(66, argp[0]);
}
+ for (unsigned i = 0; i < pipelines.size(); ++i)
+ wait(NULL);
}
cout << "Done!\n";