Browse Source

Shell: Add append operator (>>)

Fixes #93.
Robin Burchell 6 years ago
parent
commit
aee99b05a6
3 changed files with 72 additions and 37 deletions
  1. 15 1
      Shell/Parser.cpp
  2. 2 1
      Shell/Parser.h
  3. 55 35
      Shell/main.cpp

+ 15 - 1
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();

+ 2 - 1
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 };

+ 55 - 35
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
             }
         }
     }