Pipes: A first working version
1) pipes have their own dup2 control 2) a filtering in input to change all joined | is also provided
This commit is contained in:
parent
8671686e80
commit
629f634f5d
@ -9,7 +9,7 @@ int main(int argc, char* argv[]) try {
|
|||||||
std::ifstream file(argv[1]);
|
std::ifstream file(argv[1]);
|
||||||
|
|
||||||
while (std::getline (file, line, '\n')) {
|
while (std::getline (file, line, '\n')) {
|
||||||
s.parse(line).execute();
|
s.parse(snel::filter(line)).execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // interactive mode
|
else { // interactive mode
|
||||||
@ -19,7 +19,7 @@ int main(int argc, char* argv[]) try {
|
|||||||
std::getline (std::cin, line, '\n');
|
std::getline (std::cin, line, '\n');
|
||||||
if (line == "quit")
|
if (line == "quit")
|
||||||
break;
|
break;
|
||||||
s.parse(line).execute();
|
s.parse(snel::filter(line)).execute();
|
||||||
} while (1);
|
} while (1);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -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 ==========
|
* ========== ArgList ==========
|
||||||
*/
|
*/
|
||||||
@ -44,7 +66,7 @@ namespace snel {
|
|||||||
delete[] p;
|
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];
|
vtype it = new type[item.length()+1];
|
||||||
|
|
||||||
// get data
|
// get data
|
||||||
@ -92,7 +114,7 @@ namespace snel {
|
|||||||
}
|
}
|
||||||
Child& Child::make_arguments () {
|
Child& Child::make_arguments () {
|
||||||
bool in{false}, out{false}, err{false};
|
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;
|
bool CanRedirectOut = (!pipe_.to) ? true : false;
|
||||||
|
|
||||||
for (auto& t: command) {
|
for (auto& t: command) {
|
||||||
@ -132,8 +154,10 @@ namespace snel {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Child::execute(const Child* previous) {
|
bool Child::execute(std::vector<Child>::iterator it, bool first) {
|
||||||
bool stop = {false};
|
bool stop = {false};
|
||||||
|
if (!first) --it;
|
||||||
|
Child& previous = *it;
|
||||||
|
|
||||||
// Check parent redirection
|
// Check parent redirection
|
||||||
redirect_std_if (filenames[STDIN_], STDIN_);
|
redirect_std_if (filenames[STDIN_], STDIN_);
|
||||||
@ -156,10 +180,9 @@ namespace snel {
|
|||||||
if ((dup2(pipe_.fd[1], STDOUT_)) == -1) // redirect output
|
if ((dup2(pipe_.fd[1], STDOUT_)) == -1) // redirect output
|
||||||
throw Error("Child pipe[to]: Can not redirect through pipe");
|
throw Error("Child pipe[to]: Can not redirect through pipe");
|
||||||
}
|
}
|
||||||
else if ((previous!= nullptr) && pipe_.from) { // receiveing child
|
else if (!first && 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
|
||||||
close (previous->pipe().fd[1]); // close the write end
|
if ((dup2(previous.pipe().fd[0], STDIN_)) == -1) // redirect input
|
||||||
if ((dup2(previous->pipe().fd[0], STDIN_)) == -1) // redirect input
|
|
||||||
throw Error("Child pipe[from]: Can not redirect through pipe");
|
throw Error("Child pipe[from]: Can not redirect through pipe");
|
||||||
}
|
}
|
||||||
execvp(arguments.front(), arguments.data());
|
execvp(arguments.front(), arguments.data());
|
||||||
@ -169,7 +192,8 @@ namespace snel {
|
|||||||
}
|
}
|
||||||
else { // parent
|
else { // parent
|
||||||
if (pipe_.to) close (pipe_.fd[1]);
|
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;
|
int exit_status;
|
||||||
waitpid(pid, &exit_status, 0); // wait child process to finish
|
waitpid(pid, &exit_status, 0); // wait child process to finish
|
||||||
@ -233,14 +257,16 @@ namespace snel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Sequencer& Sequencer::execute() {
|
Sequencer& Sequencer::execute() {
|
||||||
for (auto& batch : seq_)
|
for (auto& batch : seq_) {
|
||||||
|
bool first;
|
||||||
|
first = true;
|
||||||
for (auto it = batch.begin() ; it != batch.end(); ++it) {
|
for (auto it = batch.begin() ; it != batch.end(); ++it) {
|
||||||
Child& command = *it;
|
Child& command = *it;
|
||||||
Child p = (it != batch.begin()) ? std::prev(it) : Child{};
|
if (command.make_arguments().execute(it, first))
|
||||||
if (command.make_arguments().execute(p))
|
|
||||||
break;
|
break;
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
seq_.clear();
|
seq_.clear();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,13 @@ namespace snel {
|
|||||||
constexpr fd_t STDOUT_ = STDOUT_FILENO;
|
constexpr fd_t STDOUT_ = STDOUT_FILENO;
|
||||||
constexpr fd_t STDERR_ = STDERR_FILENO;
|
constexpr fd_t STDERR_ = STDERR_FILENO;
|
||||||
|
|
||||||
|
std::string filter (const std::string in);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct ArgList {
|
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 = type*; // Vector type
|
||||||
using vtype_ptr = vtype*; // Pointer to vector type
|
using vtype_ptr = vtype*; // Pointer to vector type
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ namespace snel {
|
|||||||
ArgList(const ArgList&) = default;
|
ArgList(const ArgList&) = default;
|
||||||
ArgList(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(); }
|
vtype front () { return args_.front(); }
|
||||||
size_t size () { return args_.size(); }
|
size_t size () { return args_.size(); }
|
||||||
|
|
||||||
@ -73,12 +75,12 @@ namespace snel {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
~Child ();
|
~Child ();
|
||||||
Child () noexcept = default;
|
Child () = default;
|
||||||
Child (const command_t& c) : command{c} { }
|
Child (const command_t& c) : command{c} { }
|
||||||
Child (command_t&& c) : command{std::move(c)} { }
|
Child (command_t&& c) : command{std::move(c)} { }
|
||||||
|
|
||||||
Child& make_arguments ();
|
Child& make_arguments ();
|
||||||
bool execute (const Child* previous);
|
bool execute(std::vector<Child>::iterator it, bool first);
|
||||||
Pipe& pipe() { return pipe_; }
|
Pipe& pipe() { return pipe_; }
|
||||||
private:
|
private:
|
||||||
void redirect_std_if(std::string fn, fd_t std_fd);
|
void redirect_std_if(std::string fn, fd_t std_fd);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user