blob: b76790df6bce506489da8f7f52c93e5fea841785 [file] [log] [blame] [edit]
// Copyright 2016 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 <dirent.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/directory.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/syslog/global.h>
#include <lib/trace-provider/provider.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <src/lib/files/directory.h>
#include "src/lib/fxl/command_line.h"
#include "src/sys/appmgr/appmgr.h"
#include "src/sys/appmgr/moniker.h"
#include "src/sys/lib/stdout-to-debuglog/cpp/stdout-to-debuglog.h"
namespace {
// Returns the set of service names that should be proxied to the root realm
// from appmgr's namespace
std::vector<std::string> RootRealmServices() {
std::vector<std::string> res;
bool success = files::ReadDirContents("/svc_for_sys", &res);
if (!success) {
FX_LOGS(WARNING) << "failed to read /svc_for_sys (" << errno
<< "), not forwarding services to sys realm";
return std::vector<std::string>();
}
return res;
}
// Creates a zircon socket and sets it to appmgr's stdin.
zx_status_t InitStdinSocket() {
zx::socket reader, writer;
// Create a socket pair for stdin. We'll just discard the writer so stdin always looks like it's
// closed.
zx_status_t status = zx::socket::create(0, &writer, &reader);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "failed to create stdin socket: " << zx_status_get_string(status);
return status;
}
status = reader.replace(ZX_RIGHTS_BASIC | ZX_RIGHT_READ, &reader);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "failed to replace stdin reader: " << zx_status_get_string(status);
return status;
}
fdio_t* io;
status = fdio_create(reader.release(), &io);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "failed to create fdio struct for stdin reader: "
<< zx_status_get_string(status);
}
int fd = fdio_bind_to_fd(io, STDIN_FILENO, STDIN_FILENO);
if (fd != STDIN_FILENO) {
FX_LOGS(ERROR) << "failed to bind socket to stdin";
return ZX_ERR_BAD_STATE;
}
return ZX_OK;
}
} // namespace
int main(int argc, char** argv) {
// Appmgr can't connect to the logging service just yet. Fall back to stderr to not lose any logs
// in the meantime.
fx_logger_activate_fallback(fx_log_get_logger(), -1);
// Wire up standard streams. This sends all stdout and stderr to the debuglog.
// This is necessary, instead of using fuchsia.logger.LogSink, because we need
// to get appmgr logs before v1 components are running.
zx_status_t status = StdoutToDebuglog::Init();
if (status != ZX_OK) {
return status;
}
status = InitStdinSocket();
if (status != ZX_OK) {
return status;
}
async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
auto pa_directory_request = zx_take_startup_handle(PA_DIRECTORY_REQUEST);
zx::channel svc_for_sys_server, svc_for_sys_client;
status = zx::channel::create(0, &svc_for_sys_server, &svc_for_sys_client);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "failed to create channel: " << zx_status_get_string(status);
return status;
}
status =
fdio_open("/svc_for_sys", ZX_FS_RIGHT_READABLE | ZX_FS_FLAG_DIRECTORY | ZX_FS_RIGHT_WRITABLE,
svc_for_sys_server.release());
if (status != ZX_OK) {
FX_LOGS(WARNING) << "failed to open /svc_for_sys (" << zx_status_get_string(status)
<< "), not forwarding services to sys realm";
return status;
}
auto environment_services =
std::make_shared<sys::ServiceDirectory>(std::move(svc_for_sys_client));
// Certain services in appmgr's /svc, which is served by svchost, are added to
// the root realm so they can be routed into a nested environment (such as the
// sys realm in sysmgr) and used in components.
fuchsia::sys::ServiceListPtr root_realm_services(new fuchsia::sys::ServiceList);
root_realm_services->names = RootRealmServices();
root_realm_services->host_directory = environment_services->CloneChannel().TakeChannel();
zx::channel trace_client, trace_server;
status = zx::channel::create(0, &trace_client, &trace_server);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "failed to create tracing channel: " << status;
return status;
}
trace::TraceProvider trace_provider(std::move(trace_client), loop.dispatcher());
auto lifecycle_request = zx_take_startup_handle(PA_LIFECYCLE);
std::unordered_set<component::Moniker> lifecycle_allowlist;
lifecycle_allowlist.insert(component::Moniker{
.url = "fuchsia-pkg://fuchsia.com/basemgr#meta/basemgr.cmx", .realm_path = {"sys"}});
lifecycle_allowlist.insert(component::Moniker{
.url = "fuchsia-pkg://fuchsia.com/cobalt#meta/cobalt.cmx", .realm_path = {"sys"}});
component::AppmgrArgs args{.pa_directory_request = std::move(pa_directory_request),
.lifecycle_request = std::move(lifecycle_request),
.lifecycle_allowlist = std::move(lifecycle_allowlist),
.root_realm_services = std::move(root_realm_services),
.environment_services = std::move(environment_services),
.sysmgr_url = "fuchsia-pkg://fuchsia.com/sysmgr#meta/sysmgr.cmx",
.sysmgr_args = {},
.run_virtual_console = true,
.trace_server_channel = std::move(trace_server),
.stop_callback = [](zx_status_t status) { exit(status); }};
component::Appmgr appmgr(loop.dispatcher(), std::move(args));
loop.Run();
return 0;
}