blob: 4bc084d0cd94e2e83c998d2b48dc70bbab472902 [file] [log] [blame]
// Copyright 2017 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 <lib/async-loop/cpp/loop.h>
#include <lib/component/cpp/termination_reason.h>
#include <lib/fdio/limits.h>
#include <lib/fdio/util.h>
#include <lib/fxl/strings/string_printf.h>
#include <stdio.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <zircon/syscalls.h>
#include "lib/component/cpp/environment_services_helper.h"
using fuchsia::sys::TerminationReason;
using fxl::StringPrintf;
static fuchsia::sys::FileDescriptorPtr CloneFileDescriptor(int fd) {
zx_handle_t handles[FDIO_MAX_HANDLES] = {0, 0, 0};
uint32_t types[FDIO_MAX_HANDLES] = {
ZX_HANDLE_INVALID,
ZX_HANDLE_INVALID,
ZX_HANDLE_INVALID,
};
zx_status_t status = fdio_clone_fd(fd, 0, handles, types);
if (status <= 0)
return nullptr;
fuchsia::sys::FileDescriptorPtr result = fuchsia::sys::FileDescriptor::New();
result->type0 = types[0];
result->handle0 = zx::handle(handles[0]);
result->type1 = types[1];
result->handle1 = zx::handle(handles[1]);
result->type2 = types[2];
result->handle2 = zx::handle(handles[2]);
return result;
}
static void consume_arg(int* argc, const char*** argv) {
--(*argc);
++(*argv);
}
int main(int argc, const char** argv) {
if (argc < 2) {
fprintf(stderr, "Usage: run [-d] <program> <args>*\n");
return 1;
}
// argv[0] is the program name;
consume_arg(&argc, &argv);
bool daemonize = false;
if (std::string(argv[0]) == "-d") {
daemonize = true;
consume_arg(&argc, &argv);
}
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = argv[0];
std::string program_name = argv[0];
consume_arg(&argc, &argv);
while (argc) {
launch_info.arguments.push_back(*argv);
consume_arg(&argc, &argv);
}
async::Loop loop(&kAsyncLoopConfigAttachToThread);
auto env_services = component::GetEnvironmentServices();
// Connect to the Launcher service through our static environment.
fuchsia::sys::LauncherSyncPtr launcher;
env_services->ConnectToService(launcher.NewRequest());
if (daemonize) {
launcher->CreateComponent(std::move(launch_info), {});
return 0;
}
launch_info.out = CloneFileDescriptor(STDOUT_FILENO);
launch_info.err = CloneFileDescriptor(STDERR_FILENO);
fuchsia::sys::ComponentControllerPtr controller;
launcher->CreateComponent(std::move(launch_info), controller.NewRequest());
controller.events().OnTerminated = [&program_name](
int64_t return_code,
TerminationReason termination_reason) {
if (termination_reason != TerminationReason::EXITED) {
fprintf(stderr, "%s: %s\n", program_name.c_str(),
component::HumanReadableTerminationReason(termination_reason)
.c_str());
}
zx_process_exit(return_code);
};
loop.Run();
return 0;
}