examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

commit 539e3e7517fc4138a64aeaa3caf90cc8818cd677
parent 96e8d55747cc8e0e1b0082464be2ca874567976b
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Wed, 17 Aug 2022 23:48:19 +0100

hush: Add pipelining

Diffstat:
Msrc/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";