blob: 86cce0d6ab1bc89d130b1bcdfd65b511d0df7bcb [file] [log] [blame]
// 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