Browse Source

Pipes: A first working version

1) pipes have their own dup2 control
 2) a filtering in input to change all joined | is also provided
master
Christos Houtouridis 5 years ago
parent
commit
629f634f5d
3 changed files with 46 additions and 18 deletions
  1. +2
    -2
      src/Snel.cpp
  2. +38
    -12
      src/sequencer.cpp
  3. +6
    -4
      src/sequencer.h

+ 2
- 2
src/Snel.cpp View File

@@ -9,7 +9,7 @@ int main(int argc, char* argv[]) try {
std::ifstream file(argv[1]);

while (std::getline (file, line, '\n')) {
s.parse(line).execute();
s.parse(snel::filter(line)).execute();
}
}
else { // interactive mode
@@ -19,7 +19,7 @@ int main(int argc, char* argv[]) try {
std::getline (std::cin, line, '\n');
if (line == "quit")
break;
s.parse(line).execute();
s.parse(snel::filter(line)).execute();
} while (1);
}
return 0;


+ 38
- 12
src/sequencer.cpp View File

@@ -35,6 +35,28 @@ namespace snel {
}
}

std::string filter (const std::string in) {
std::string out;
char prev {0}, cur, next {0};

for (auto i = in.begin(); i != in.end() ; ++i) {
cur = *i;
if (cur == '|') {
if (prev != ' ') out += ' ';
next = *++i;
if (next == '|' || next == ' ') {
out += cur; cur = next; // syntax ok
}
else {
// syntax problem, insert a space
out += cur; out += ' '; cur = next;
}
}
prev = cur;
out += cur;
}
return out;
}
/*
* ========== ArgList ==========
*/
@@ -44,7 +66,7 @@ namespace snel {
delete[] p;
}
}
ArgList& ArgList::push_back(const std::basic_string<type>& item) {
ArgList& ArgList::push_back(const std::string& item) {
vtype it = new type[item.length()+1];

// get data
@@ -92,7 +114,7 @@ namespace snel {
}
Child& Child::make_arguments () {
bool in{false}, out{false}, err{false};
bool CanRedirectIn = (pipe_.from) ? true : false;
bool CanRedirectIn = (!pipe_.from) ? true : false;
bool CanRedirectOut = (!pipe_.to) ? true : false;

for (auto& t: command) {
@@ -132,8 +154,10 @@ namespace snel {
return *this;
}

bool Child::execute(const Child* previous) {
bool Child::execute(std::vector<Child>::iterator it, bool first) {
bool stop = {false};
if (!first) --it;
Child& previous = *it;

// Check parent redirection
redirect_std_if (filenames[STDIN_], STDIN_);
@@ -156,10 +180,9 @@ namespace snel {
if ((dup2(pipe_.fd[1], STDOUT_)) == -1) // redirect output
throw Error("Child pipe[to]: Can not redirect through pipe");
}
else if ((previous!= nullptr) && pipe_.from) { // receiveing child
std::cout << "from[0]=" << previous->pipe().fd[0] << " from[1]=" << previous->pipe().fd[1]<< std::endl;
close (previous->pipe().fd[1]); // close the write end
if ((dup2(previous->pipe().fd[0], STDIN_)) == -1) // redirect input
else if (!first && pipe_.from) { // receiveing child
close (previous.pipe().fd[1]); // close the write end
if ((dup2(previous.pipe().fd[0], STDIN_)) == -1) // redirect input
throw Error("Child pipe[from]: Can not redirect through pipe");
}
execvp(arguments.front(), arguments.data());
@@ -169,7 +192,8 @@ namespace snel {
}
else { // parent
if (pipe_.to) close (pipe_.fd[1]);
else if (pipe_.from) close (previous->pipe().fd[0]);
else if (!first && pipe_.from)
close (previous.pipe().fd[0]);

int exit_status;
waitpid(pid, &exit_status, 0); // wait child process to finish
@@ -233,14 +257,16 @@ namespace snel {
}

Sequencer& Sequencer::execute() {
for (auto& batch : seq_)
for (auto& batch : seq_) {
bool first;
first = true;
for (auto it = batch.begin() ; it != batch.end(); ++it) {
Child& command = *it;
Child p = (it != batch.begin()) ? std::prev(it) : Child{};
if (command.make_arguments().execute(p))
if (command.make_arguments().execute(it, first))
break;
first = false;
}
}
seq_.clear();
return *this;
}


+ 6
- 4
src/sequencer.h View File

@@ -31,11 +31,13 @@ namespace snel {
constexpr fd_t STDOUT_ = STDOUT_FILENO;
constexpr fd_t STDERR_ = STDERR_FILENO;

std::string filter (const std::string in);

/*!
*
*/
struct ArgList {
using type = char; // Basic data type
using type = typename std::string::value_type; // Basic data type
using vtype = type*; // Vector type
using vtype_ptr = vtype*; // Pointer to vector type

@@ -44,7 +46,7 @@ namespace snel {
ArgList(const ArgList&) = default;
ArgList(ArgList&&) = default;

ArgList& push_back(const std::basic_string<type>& item);
ArgList& push_back(const std::string& item);
vtype front () { return args_.front(); }
size_t size () { return args_.size(); }

@@ -73,12 +75,12 @@ namespace snel {

public:
~Child ();
Child () noexcept = default;
Child () = default;
Child (const command_t& c) : command{c} { }
Child (command_t&& c) : command{std::move(c)} { }

Child& make_arguments ();
bool execute (const Child* previous);
bool execute(std::vector<Child>::iterator it, bool first);
Pipe& pipe() { return pipe_; }
private:
void redirect_std_if(std::string fn, fd_t std_fd);


Loading…
Cancel
Save