summaryrefslogtreecommitdiff
path: root/Shell
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-07-13 09:30:09 +0430
committerAndreas Kling <kling@serenityos.org>2020-07-13 15:12:28 +0200
commitb0ce8d725a1639d90d4ead4d0a55528a389179f7 (patch)
tree0bf90b25e9971cd1345891673389eef4966778a8 /Shell
parent4c3a415dc3247e6dc4b62baffd62c952d2b9e8f7 (diff)
downloadserenity-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.
Diffstat (limited to 'Shell')
-rw-r--r--Shell/AST.cpp90
-rw-r--r--Shell/AST.h8
-rw-r--r--Shell/Shell.cpp84
-rw-r--r--Shell/Shell.h4
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;