blob: 295a5d715bd2c482925328f459199b0c52bee0b2 [file] [log] [blame]
// Copyright 2018 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 <fuchsia/virtualization/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fit/function.h>
#include <lib/sys/cpp/component_context.h>
#include <filesystem>
#include <iostream>
#include <optional>
#include "lib/sys/cpp/component_context.h"
#include "src/lib/fxl/strings/string_number_conversions.h"
#include "src/virtualization/bin/vsh/vshc.h"
static void usage() {
std::cerr << "Usage: vsh [<env_id> [<cid> [<port>]]] [-c [<arg>...]]\n";
}
template <class T>
static bool parse_number(const char* arg, const char* name, T* value,
fxl::Base base = fxl::Base::k10) {
std::string_view arg_view(arg);
if (!fxl::StringToNumberWithError(arg_view, value, base)) {
std::cerr << "Invalid " << name << ": " << arg_view << "\n";
return false;
}
return true;
}
static bool parse_args(int argc, const char** argv, async::Loop* loop,
sys::ComponentContext* context, fit::function<zx_status_t()>* func) {
if (argc < 1) {
return false;
}
std::vector<std::string> args;
int args_start = argc;
bool found_container_args = false;
for (int i = 1; i < argc; i++) {
if (found_container_args) {
args.push_back(argv[i]);
} else if (std::string_view{argv[i]} == "-c") {
args_start = i;
found_container_args = true;
}
}
if (found_container_args) {
if (args.empty()) {
args = {"lxc", "exec", "penguin", "--", "login", "-f", "machina"};
} else {
args.insert(args.begin(), {"lxc", "exec", "penguin", "--"});
}
}
// Truncate the effective argv under later consideration.
argc = args_start;
std::optional<uint32_t> env_id, cid, port;
bool success = true;
switch (argc) {
case 4:
port = -1;
success &= parse_number(argv[3], "port", &*port);
__FALLTHROUGH;
case 3:
cid = -1;
success &= parse_number(argv[2], "context ID", &*cid);
__FALLTHROUGH;
case 2:
env_id = -1;
success &= parse_number(argv[1], "environment ID", &*env_id);
__FALLTHROUGH;
case 1:
break;
default:
return false;
}
if (!success) {
return false;
}
*func = [env_id, cid, port, args, loop, context]() -> zx_status_t {
return handle_vsh(env_id, cid, port, args, loop, context);
};
return true;
}
int main(int argc, const char** argv) {
fit::function<zx_status_t()> func;
async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
auto context = sys::ComponentContext::CreateAndServeOutgoingDirectory();
if (!parse_args(argc, argv, &loop, context.get(), &func)) {
usage();
return ZX_ERR_INVALID_ARGS;
}
return func() == ZX_OK ? 0 : 1;
}