| // Copyright 2019 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/developer/cmd/executor.h" | |
| #include <lib/fdio/spawn.h> | |
| #include <lib/zx/process.h> | |
| #include <zircon/compiler.h> | |
| #include <map> | |
| #include <memory> | |
| #include <vector> | |
| #include "src/developer/cmd/legacy/builtins.h" | |
| #include "src/developer/cmd/tasks/cd_task.h" | |
| #include "src/developer/cmd/tasks/getenv_task.h" | |
| #include "src/developer/cmd/tasks/process_task.h" | |
| #include "src/developer/cmd/tasks/quit_task.h" | |
| #include "src/developer/cmd/tasks/setenv_task.h" | |
| #include "src/developer/cmd/tasks/synchronous_task.h" | |
| #include "src/developer/cmd/tasks/unsetenv_task.h" | |
| namespace cmd { | |
| namespace { | |
| template <typename TaskType> | |
| std::unique_ptr<Task> CreateTask(async_dispatcher_t* dispatcher) { | |
| return std::make_unique<TaskType>(dispatcher); | |
| } | |
| template <SynchronousTask::Function Impl> | |
| std::unique_ptr<Task> CreateSynchronousTask(async_dispatcher_t* dispatcher) { | |
| return std::make_unique<SynchronousTask>(dispatcher, Impl); | |
| } | |
| } // namespace | |
| Executor::Executor(async_dispatcher_t* dispatcher) | |
| : dispatcher_(dispatcher), | |
| builtin_commands_({ | |
| {"cd", &CreateTask<CdTask>}, | |
| {"cp", &CreateSynchronousTask<zxc_mv_or_cp>}, | |
| {"dm", &CreateSynchronousTask<zxc_dm>}, | |
| {"dump", &CreateSynchronousTask<zxc_dump>}, | |
| {"exit", &CreateTask<QuitTask>}, | |
| {"getenv", &CreateTask<GetenvTask>}, | |
| {"k", &CreateSynchronousTask<zxc_k>}, | |
| {"list", &CreateSynchronousTask<zxc_list>}, | |
| {"ls", &CreateSynchronousTask<zxc_ls>}, | |
| {"mkdir", &CreateSynchronousTask<zxc_mkdir>}, | |
| {"msleep", &CreateSynchronousTask<zxc_msleep>}, | |
| {"mv", &CreateSynchronousTask<zxc_mv_or_cp>}, | |
| {"quit", &CreateTask<QuitTask>}, | |
| {"rm", &CreateSynchronousTask<zxc_rm>}, | |
| {"setenv", &CreateTask<SetenvTask>}, | |
| {"unsetenv", &CreateTask<UnsetenvTask>}, | |
| }) {} | |
| Executor::~Executor() = default; | |
| zx_status_t Executor::Execute(Command command, Task::CompletionCallback callback) { | |
| if (command.is_empty()) { | |
| return ZX_ERR_NEXT; | |
| } | |
| foreground_task_ = FindAndCreateTask(command.args()[0]); | |
| return foreground_task_->Execute(std::move(command), std::move(callback)); | |
| } | |
| void Executor::KillForegroundTask() { foreground_task_.reset(); } | |
| void Executor::Complete(Autocomplete* autocomplete) { | |
| if (autocomplete->tokens().empty()) { | |
| CompleteCommand(autocomplete); | |
| return; | |
| } | |
| std::vector<std::string> result; | |
| FindAndCreateTask(autocomplete->tokens().front())->Complete(autocomplete); | |
| } | |
| std::unique_ptr<Task> Executor::FindAndCreateTask(const std::string& name) { | |
| if (ProcessTask::SearchPath(name).empty()) { | |
| auto it = builtin_commands_.find(name); | |
| if (it != builtin_commands_.end()) { | |
| return it->second(dispatcher_); | |
| } | |
| } | |
| return std::make_unique<ProcessTask>(dispatcher_); | |
| } | |
| void Executor::CompleteCommand(Autocomplete* autocomplete) { | |
| std::vector<std::string> result; | |
| for (const auto& entry : builtin_commands_) { | |
| const std::string& key = entry.first; | |
| if (key.find(autocomplete->fragment()) == 0u) { | |
| autocomplete->AddCompletion(key); | |
| } | |
| } | |
| ProcessTask::CompleteCommand(autocomplete); | |
| } | |
| } // namespace cmd |