diff options
author | Robin Burchell <robin+git@viroteck.net> | 2019-05-26 00:38:11 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-05-26 01:32:05 +0200 |
commit | aee99b05a69d0d01debaa273bcb9b10c9411a97a (patch) | |
tree | e2eab3de3d1fc9b186449bbc0cf31e5dc4ef95bb | |
parent | c6e79bd53a37aa0d9fb7c610d7d251a9e1b0a11d (diff) | |
download | serenity-aee99b05a69d0d01debaa273bcb9b10c9411a97a.zip |
Shell: Add append operator (>>)
Fixes #93.
-rw-r--r-- | Shell/Parser.cpp | 16 | ||||
-rw-r--r-- | Shell/Parser.h | 3 | ||||
-rw-r--r-- | Shell/main.cpp | 90 |
3 files changed, 72 insertions, 37 deletions
diff --git a/Shell/Parser.cpp b/Shell/Parser.cpp index 5adc36cd7b..d49027714b 100644 --- a/Shell/Parser.cpp +++ b/Shell/Parser.cpp @@ -60,7 +60,9 @@ Vector<Subcommand> Parser::parse() if (ch == '>') { commit_token(); begin_redirect_write(STDOUT_FILENO); - m_state = State::InRedirectionPath; + + // Search for another > for append. + m_state = State::InWriteAppendOrRedirectionPath; break; } if (ch == '<') { @@ -79,6 +81,18 @@ Vector<Subcommand> Parser::parse() } m_token.append(ch); break; + case State::InWriteAppendOrRedirectionPath: + if (ch == '>') { + commit_token(); + m_state = State::InRedirectionPath; + ASSERT(m_redirections.size()); + m_redirections[m_redirections.size() - 1].type = Redirection::FileWriteAppend; + break; + } + + // Not another > means that it's probably a path. + m_state = InRedirectionPath; + [[fallthrough]]; case State::InRedirectionPath: if (ch == '<') { commit_token(); diff --git a/Shell/Parser.h b/Shell/Parser.h index 3112cc6cb9..ed94a888dc 100644 --- a/Shell/Parser.h +++ b/Shell/Parser.h @@ -4,7 +4,7 @@ #include <AK/Vector.h> struct Redirection { - enum Type { Pipe, FileWrite, FileRead, Rewire }; + enum Type { Pipe, FileWrite, FileWriteAppend, FileRead, Rewire }; Type type; int fd { -1 }; int rewire_fd { -1 }; @@ -33,6 +33,7 @@ private: Free, InSingleQuotes, InDoubleQuotes, + InWriteAppendOrRedirectionPath, InRedirectionPath, }; State m_state { Free }; diff --git a/Shell/main.cpp b/Shell/main.cpp index 5c019f4826..ffe4f550ef 100644 --- a/Shell/main.cpp +++ b/Shell/main.cpp @@ -233,24 +233,27 @@ static int run_command(const String& cmd) #ifdef SH_DEBUG for (int i = 0; i < subcommands.size(); ++i) { for (int j = 0; j < i; ++j) - printf(" "); + dbgprintf(" "); for (auto& arg : subcommands[i].args) { - printf("<%s> ", arg.characters()); + dbgprintf("<%s> ", arg.characters()); } - printf("\n"); + dbgprintf("\n"); for (auto& redirecton : subcommands[i].redirections) { for (int j = 0; j < i; ++j) - printf(" "); - printf(" "); + dbgprintf(" "); + dbgprintf(" "); switch (redirecton.type) { case Redirection::Pipe: - printf("Pipe\n"); + dbgprintf("Pipe\n"); break; case Redirection::FileRead: - printf("fd:%d = FileRead: %s\n", redirecton.fd, redirecton.path.characters()); + dbgprintf("fd:%d = FileRead: %s\n", redirecton.fd, redirecton.path.characters()); break; case Redirection::FileWrite: - printf("fd:%d = FileWrite: %s\n", redirecton.fd, redirecton.path.characters()); + dbgprintf("fd:%d = FileWrite: %s\n", redirecton.fd, redirecton.path.characters()); + break; + case Redirection::FileWriteAppend: + dbgprintf("fd:%d = FileWriteAppend: %s\n", redirecton.fd, redirecton.path.characters()); break; default: break; @@ -267,36 +270,53 @@ static int run_command(const String& cmd) for (int i = 0; i < subcommands.size(); ++i) { auto& subcommand = subcommands[i]; for (auto& redirection : subcommand.redirections) { - if (redirection.type == Redirection::Pipe) { - int pipefd[2]; - int rc = pipe(pipefd); - if (rc < 0) { - perror("pipe"); - return 1; + switch (redirection.type) { + case Redirection::Pipe: { + int pipefd[2]; + int rc = pipe(pipefd); + if (rc < 0) { + perror("pipe"); + return 1; + } + subcommand.redirections.append({ Redirection::Rewire, STDOUT_FILENO, pipefd[1] }); + auto& next_command = subcommands[i + 1]; + next_command.redirections.append({ Redirection::Rewire, STDIN_FILENO, pipefd[0] }); + fds.add(pipefd[0]); + fds.add(pipefd[1]); + break; } - subcommand.redirections.append({ Redirection::Rewire, STDOUT_FILENO, pipefd[1] }); - auto& next_command = subcommands[i + 1]; - next_command.redirections.append({ Redirection::Rewire, STDIN_FILENO, pipefd[0] }); - fds.add(pipefd[0]); - fds.add(pipefd[1]); - } - if (redirection.type == Redirection::FileWrite) { - int fd = open(redirection.path.characters(), O_WRONLY | O_CREAT, 0666); - if (fd < 0) { - perror("open"); - return 1; + case Redirection::FileWriteAppend: { + int fd = open(redirection.path.characters(), O_WRONLY | O_CREAT | O_APPEND, 0666); + if (fd < 0) { + perror("open"); + return 1; + } + subcommand.redirections.append({ Redirection::Rewire, redirection.fd, fd }); + fds.add(fd); + break; } - subcommand.redirections.append({ Redirection::Rewire, redirection.fd, fd }); - fds.add(fd); - } - if (redirection.type == Redirection::FileRead) { - int fd = open(redirection.path.characters(), O_RDONLY); - if (fd < 0) { - perror("open"); - return 1; + case Redirection::FileWrite: { + int fd = open(redirection.path.characters(), O_WRONLY | O_CREAT, 0666); + if (fd < 0) { + perror("open"); + return 1; + } + subcommand.redirections.append({ Redirection::Rewire, redirection.fd, fd }); + fds.add(fd); + break; + } + case Redirection::FileRead: { + int fd = open(redirection.path.characters(), O_RDONLY); + if (fd < 0) { + perror("open"); + return 1; + } + subcommand.redirections.append({ Redirection::Rewire, redirection.fd, fd }); + fds.add(fd); + break; } - subcommand.redirections.append({ Redirection::Rewire, redirection.fd, fd }); - fds.add(fd); + case Redirection::Rewire: + break; // ignore } } } |