Browse Source

Shell: Redirectiong from multiple-digit fds

Karol Baraniecki 5 years ago
parent
commit
431abc8846
1 changed files with 45 additions and 0 deletions
  1. 45 0
      Shell/Parser.cpp

+ 45 - 0
Shell/Parser.cpp

@@ -103,6 +103,51 @@ Vector<Command> Parser::parse()
                 m_state = State::InDoubleQuotes;
                 m_state = State::InDoubleQuotes;
                 break;
                 break;
             }
             }
+            
+            // redirection from zsh-style multi-digit fd, such as {10}>file
+            if (ch == '{') {
+                bool is_multi_fd_redirection = false;
+                int redir_end = i + 1;
+
+                while (redir_end < m_input.length()) {
+                    char lookahead_ch = m_input.characters()[redir_end];
+                    if (isdigit(lookahead_ch)) {
+                        ++redir_end;
+                        continue;
+                    }
+                    if (lookahead_ch == '}' && redir_end + 1 != m_input.length()) {
+                        // Disallow {}> and {}<
+                        if (redir_end == i + 1)
+                            break;
+
+                        ++redir_end;
+                        if (m_input.characters()[redir_end] == '>' || m_input.characters()[redir_end] == '<')
+                            is_multi_fd_redirection = true;
+                        break;
+                    }
+                    break;
+                }
+
+                if (is_multi_fd_redirection) {
+                    commit_token();
+
+                    int fd = atoi(&m_input.characters()[i + 1]);
+
+                    if (m_input.characters()[redir_end] == '>') {
+                        begin_redirect_write(fd);
+                        // Search for another > for append.
+                        m_state = State::InWriteAppendOrRedirectionPath;
+                    }
+                    if (m_input.characters()[redir_end] == '<') {
+                        begin_redirect_read(fd);
+                        m_state = State::InRedirectionPath;
+                    }
+
+                    i = redir_end;
+
+                    break;
+                }
+            }
             if (isdigit(ch)) {
             if (isdigit(ch)) {
                 if (i != m_input.length() - 1) {
                 if (i != m_input.length() - 1) {
                     char next_ch = m_input.characters()[i + 1];
                     char next_ch = m_input.characters()[i + 1];