summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Burchell <robin+git@viroteck.net>2019-05-26 00:38:11 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-05-26 01:32:05 +0200
commitaee99b05a69d0d01debaa273bcb9b10c9411a97a (patch)
treee2eab3de3d1fc9b186449bbc0cf31e5dc4ef95bb
parentc6e79bd53a37aa0d9fb7c610d7d251a9e1b0a11d (diff)
downloadserenity-aee99b05a69d0d01debaa273bcb9b10c9411a97a.zip
Shell: Add append operator (>>)
Fixes #93.
-rw-r--r--Shell/Parser.cpp16
-rw-r--r--Shell/Parser.h3
-rw-r--r--Shell/main.cpp90
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
}
}
}