diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-07-13 09:30:09 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-13 15:12:28 +0200 |
commit | b0ce8d725a1639d90d4ead4d0a55528a389179f7 (patch) | |
tree | 0bf90b25e9971cd1345891673389eef4966778a8 | |
parent | 4c3a415dc3247e6dc4b62baffd62c952d2b9e8f7 (diff) | |
download | serenity-b0ce8d725a1639d90d4ead4d0a55528a389179f7.zip |
Shell: Move out run_commands and expand_aliases to be Shell member fns
This makes running commands from outside the AST chain easier.
-rw-r--r-- | Shell/AST.cpp | 90 | ||||
-rw-r--r-- | Shell/AST.h | 8 | ||||
-rw-r--r-- | Shell/Shell.cpp | 84 | ||||
-rw-r--r-- | Shell/Shell.h | 4 |
4 files changed, 99 insertions, 87 deletions
diff --git a/Shell/AST.cpp b/Shell/AST.cpp index 4bbf3777ba..1e2261ba2e 100644 --- a/Shell/AST.cpp +++ b/Shell/AST.cpp @@ -742,79 +742,7 @@ RefPtr<Value> Execute::run(RefPtr<Shell> shell) if (m_command->would_execute()) return m_command->run(shell); - auto initial_commands = m_command->run(shell)->resolve_as_commands(shell); - decltype(initial_commands) commands; - - Function<void(Command&)> resolve_aliases_and_append = [&](auto& command) { - if (!command.argv.is_empty()) { - auto alias = shell->resolve_alias(command.argv[0]); - if (!alias.is_null()) { - auto argv0 = command.argv.take_first(); - auto subcommand_ast = Parser { alias }.parse(); - if (subcommand_ast) { - while (subcommand_ast->is_execute()) { - auto* ast = static_cast<Execute*>(subcommand_ast.ptr()); - subcommand_ast = ast->command(); - } - RefPtr<Node> substitute = create<Join>(position(), move(subcommand_ast), create<CommandLiteral>(position(), command)); - for (auto& subst_command : substitute->run(shell)->resolve_as_commands(shell)) { - if (!subst_command.argv.is_empty() && subst_command.argv.first() == argv0) // Disallow an alias resolving to itself. - commands.append(subst_command); - else - resolve_aliases_and_append(subst_command); - } - } else { - commands.append(command); - } - } else { - commands.append(command); - } - } else { - commands.append(command); - } - }; - - for (auto& command : initial_commands) - resolve_aliases_and_append(command); - - Vector<RefPtr<Job>> jobs_to_wait_for; - - auto run_commands = [&](auto& commands) { - for (auto& command : commands) { -#ifdef EXECUTE_DEBUG - dbg() << "Command"; - for (auto& arg : command.argv) - dbg() << "argv: " << arg; - for (auto& redir : command.redirections) { - if (redir->is_path_redirection()) { - auto path_redir = (const PathRedirection*)redir.ptr(); - dbg() << "redir path " << (int)path_redir->direction << " " << path_redir->path << " <-> " << path_redir->fd; - } else if (redir->is_fd_redirection()) { - auto fd_redir = (const FdRedirection*)redir.ptr(); - dbg() << "redir fd " << fd_redir->source_fd << " -> " << fd_redir->dest_fd; - } else if (redir->is_close_redirection()) { - auto close_redir = (const CloseRedirection*)redir.ptr(); - dbg() << "close fd " << close_redir->fd; - } else { - ASSERT_NOT_REACHED(); - } - } -#endif - job = shell->run_command(command); - - if (command.should_wait) { - shell->block_on_job(job); - } else { - if (command.is_pipe_source) { - jobs_to_wait_for.append(job); - } else if (command.should_notify_if_in_background) { - if (job) - job->set_running_in_background(true); - shell->restore_stdin(); - } - } - } - }; + auto commands = shell->expand_aliases(m_command->run(shell)->resolve_as_commands(shell)); if (m_capture_stdout) { int pipefd[2]; @@ -860,9 +788,7 @@ RefPtr<Value> Execute::run(RefPtr<Shell> shell) try_read(); }; - run_commands(commands); - - for (auto job : jobs_to_wait_for) { + for (auto job : shell->run_commands(commands)) { shell->block_on_job(job); } @@ -877,12 +803,14 @@ RefPtr<Value> Execute::run(RefPtr<Shell> shell) return create<StringValue>(builder.build(), shell->local_variable_or("IFS", "\n"), shell->options.inline_exec_keep_empty_segments); } - run_commands(commands); - for (auto job : jobs_to_wait_for) { + RefPtr<Job> last_job; + + for (auto& job : shell->run_commands(commands)) { shell->block_on_job(job); + last_job = move(job); } - return create<JobValue>(move(job)); + return create<JobValue>(move(last_job)); } void Execute::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata) @@ -1969,7 +1897,7 @@ Vector<String> TildeValue::resolve_as_list(RefPtr<Shell> shell) return { shell->expand_tilde(builder.to_string()) }; } -Result<RefPtr<Rewiring>, String> CloseRedirection::apply() +Result<RefPtr<Rewiring>, String> CloseRedirection::apply() const { return static_cast<RefPtr<Rewiring>>((adopt(*new Rewiring(fd, fd, Rewiring::Close::ImmediatelyCloseDestination)))); } @@ -1978,7 +1906,7 @@ CloseRedirection::~CloseRedirection() { } -Result<RefPtr<Rewiring>, String> PathRedirection::apply() +Result<RefPtr<Rewiring>, String> PathRedirection::apply() const { auto check_fd_and_return = [my_fd = this->fd](int fd, const String& path) -> Result<RefPtr<Rewiring>, String> { if (fd < 0) { diff --git a/Shell/AST.h b/Shell/AST.h index 4c30150a84..2e9c74ea5c 100644 --- a/Shell/AST.h +++ b/Shell/AST.h @@ -77,7 +77,7 @@ struct Rewiring : public RefCounted<Rewiring> { }; struct Redirection : public RefCounted<Redirection> { - virtual Result<RefPtr<Rewiring>, String> apply() = 0; + virtual Result<RefPtr<Rewiring>, String> apply() const = 0; virtual ~Redirection(); virtual bool is_path_redirection() const { return false; } virtual bool is_fd_redirection() const { return false; } @@ -87,7 +87,7 @@ struct Redirection : public RefCounted<Redirection> { struct CloseRedirection : public Redirection { int fd { -1 }; - virtual Result<RefPtr<Rewiring>, String> apply() override; + virtual Result<RefPtr<Rewiring>, String> apply() const override; virtual ~CloseRedirection(); CloseRedirection(int fd) : fd(fd) @@ -108,7 +108,7 @@ struct PathRedirection : public Redirection { ReadWrite, } direction { Read }; - virtual Result<RefPtr<Rewiring>, String> apply() override; + virtual Result<RefPtr<Rewiring>, String> apply() const override; virtual ~PathRedirection(); PathRedirection(String path, int fd, decltype(direction) direction) : path(move(path)) @@ -124,7 +124,7 @@ private: struct FdRedirection : public Redirection , public Rewiring { - virtual Result<RefPtr<Rewiring>, String> apply() override { return static_cast<RefPtr<Rewiring>>(this); } + virtual Result<RefPtr<Rewiring>, String> apply() const override { return static_cast<RefPtr<Rewiring>>(this); } virtual ~FdRedirection(); FdRedirection(int source, int dest, Rewiring::Close close) : Rewiring(source, dest, close) diff --git a/Shell/Shell.cpp b/Shell/Shell.cpp index 09faef91bb..2ee2e9f949 100644 --- a/Shell/Shell.cpp +++ b/Shell/Shell.cpp @@ -271,6 +271,45 @@ Vector<String> Shell::expand_globs(Vector<StringView> path_segments, const Strin } } +Vector<AST::Command> Shell::expand_aliases(Vector<AST::Command> initial_commands) +{ + Vector<AST::Command> commands; + + Function<void(AST::Command&)> resolve_aliases_and_append = [&](auto& command) { + if (!command.argv.is_empty()) { + auto alias = resolve_alias(command.argv[0]); + if (!alias.is_null()) { + auto argv0 = command.argv.take_first(); + auto subcommand_ast = Parser { alias }.parse(); + if (subcommand_ast) { + while (subcommand_ast->is_execute()) { + auto* ast = static_cast<AST::Execute*>(subcommand_ast.ptr()); + subcommand_ast = ast->command(); + } + AST::Node& substitute = *new AST::Join(subcommand_ast->position(), subcommand_ast, *new AST::CommandLiteral(subcommand_ast->position(), command)); + for (auto& subst_command : substitute.run(*this)->resolve_as_commands(*this)) { + if (!subst_command.argv.is_empty() && subst_command.argv.first() == argv0) // Disallow an alias resolving to itself. + commands.append(subst_command); + else + resolve_aliases_and_append(subst_command); + } + } else { + commands.append(command); + } + } else { + commands.append(command); + } + } else { + commands.append(command); + } + }; + + for (auto& command : initial_commands) + resolve_aliases_and_append(command); + + return commands; +} + String Shell::resolve_path(String path) const { if (!path.starts_with('/')) @@ -349,7 +388,7 @@ int Shell::run_command(const StringView& cmd) return last_return_code; } -RefPtr<Job> Shell::run_command(AST::Command& command) +RefPtr<Job> Shell::run_command(const AST::Command& command) { FileDescriptionCollector fds; @@ -494,6 +533,49 @@ RefPtr<Job> Shell::run_command(AST::Command& command) return *job; } +Vector<RefPtr<Job>> Shell::run_commands(Vector<AST::Command>& commands) +{ + Vector<RefPtr<Job>> jobs_to_wait_for; + + for (auto& command : commands) { +#ifdef SH_DEBUG + dbg() << "Command"; + for (auto& arg : command.argv) + dbg() << "argv: " << arg; + for (auto& redir : command.redirections) { + if (redir->is_path_redirection()) { + auto path_redir = (const AST::PathRedirection*)redir.ptr(); + dbg() << "redir path " << (int)path_redir->direction << " " << path_redir->path << " <-> " << path_redir->fd; + } else if (redir->is_fd_redirection()) { + auto fd_redir = (const AST::FdRedirection*)redir.ptr(); + dbg() << "redir fd " << fd_redir->source_fd << " -> " << fd_redir->dest_fd; + } else if (redir->is_close_redirection()) { + auto close_redir = (const AST::CloseRedirection*)redir.ptr(); + dbg() << "close fd " << close_redir->fd; + } else { + ASSERT_NOT_REACHED(); + } + } +#endif + auto job = run_command(command); + + if (command.should_wait) { + block_on_job(job); + jobs_to_wait_for.append(job); + } else { + if (command.is_pipe_source) { + jobs_to_wait_for.append(job); + } else if (command.should_notify_if_in_background) { + if (job) + job->set_running_in_background(true); + restore_stdin(); + } + } + } + + return jobs_to_wait_for; +} + bool Shell::run_file(const String& filename, bool explicitly_invoked) { auto file_result = Core::File::open(filename, Core::File::ReadOnly); diff --git a/Shell/Shell.h b/Shell/Shell.h index b122e38b5e..72b500ab40 100644 --- a/Shell/Shell.h +++ b/Shell/Shell.h @@ -73,7 +73,8 @@ public: constexpr static auto global_init_file_path = "/etc/shellrc"; int run_command(const StringView&); - RefPtr<Job> run_command(AST::Command&); + RefPtr<Job> run_command(const AST::Command&); + Vector<RefPtr<Job>> run_commands(Vector<AST::Command>&); bool run_file(const String&, bool explicitly_invoked = true); bool run_builtin(int argc, const char** argv, int& retval); bool has_builtin(const StringView&) const; @@ -83,6 +84,7 @@ public: static String expand_tilde(const String&); static Vector<String> expand_globs(const StringView& path, StringView base); static Vector<String> expand_globs(Vector<StringView> path_segments, const StringView& base); + Vector<AST::Command> expand_aliases(Vector<AST::Command>); String resolve_path(String) const; String resolve_alias(const String&) const; |