Esempio n. 1
0
int fx_muxer_t::parse_args_and_execute(const pal::string_t& own_dir, int argoff, int argc, const pal::char_t* argv[], bool exec_mode, bool* is_an_app)
{
    *is_an_app = true;

    std::vector<pal::string_t> known_opts = { _X("--additionalprobingpath") };
    if (exec_mode)
    {
        known_opts.push_back(_X("--depsfile"));
    }

    // Parse the known muxer arguments if any.
    int num_parsed = 0;
    std::unordered_map<pal::string_t, std::vector<pal::string_t>> opts;
    if (!parse_known_args(argc - argoff, &argv[argoff], known_opts, &opts, &num_parsed))
    {
        trace::error(_X("Failed to parse supported arguments."));
        return InvalidArgFailure;
    }
    int cur_i = argoff + num_parsed;
    if (cur_i >= argc)
    {
        return muxer_usage();
    }

    pal::string_t app_candidate = argv[cur_i];
    bool is_app_runnable = ends_with(app_candidate, _X(".dll"), false) || ends_with(app_candidate, _X(".exe"), false);

    // If exec mode is on, then check we have a dll at this point
    if (exec_mode)
    {
        if (!is_app_runnable)
        {
            trace::error(_X("dotnet exec needs a dll to execute. Try dotnet [--help]"));
            return InvalidArgFailure;
        }
    }
    // For non-exec, there is CLI invocation or app.dll execution after known args.
    else
    {
        // Test if we have a real dll at this point.
        if (!is_app_runnable)
        {
            // No we don't have a dll, this must be routed to the CLI.
            *is_an_app = false;
            return Success;
        }
    }

    // Transform dotnet [exec] [--additionalprobingpath path] [--depsfile file] dll [args] -> dotnet dll [args]

    std::vector<const pal::char_t*> vec_argv;
    const pal::char_t** new_argv = argv;
    int new_argc = argc;
    if (cur_i != 1)
    {
        vec_argv.resize(argc - cur_i + 1, 0); // +1 for dotnet
        memcpy(vec_argv.data() + 1, argv + cur_i, (argc - cur_i) * sizeof(pal::char_t*));
        vec_argv[0] = argv[0];
        new_argv = vec_argv.data();
        new_argc = vec_argv.size();
    }

    pal::string_t opts_deps_file = _X("--depsfile");
    pal::string_t opts_probe_path = _X("--additionalprobingpath");
    pal::string_t deps_file = get_last_known_arg(opts, opts_deps_file, _X(""));
    std::vector<pal::string_t> probe_paths = opts.count(opts_probe_path) ? opts[opts_probe_path] : std::vector<pal::string_t>();

    trace::verbose(_X("Current argv is %s"), app_candidate.c_str());

    pal::string_t app_or_deps = deps_file.empty() ? app_candidate : deps_file;
    pal::string_t no_json = app_candidate;
    pal::string_t dev_config_file;
    auto config_file = get_runtime_config_from_file(no_json, &dev_config_file);
    runtime_config_t config(config_file, dev_config_file);
    for (const auto& path : config.get_probe_paths())
    {
        probe_paths.push_back(path);
    }

    if (!config.is_valid())
    {
        trace::error(_X("Invalid runtimeconfig.json [%s] [%s]"), config.get_path().c_str(), config.get_dev_path().c_str());
        return StatusCode::InvalidConfigFile;
    }
    if (!deps_file.empty() && !pal::file_exists(deps_file))
    {
        trace::error(_X("Deps file [%s] specified but doesn't exist"), deps_file.c_str());
        return StatusCode::InvalidArgFailure;
    }

    if (config.get_portable())
    {
        trace::verbose(_X("Executing as a portable app as per config file [%s]"), config_file.c_str());
        pal::string_t fx_dir = resolve_fx_dir(own_dir, &config);
        corehost_init_t init(deps_file, probe_paths, fx_dir, host_mode_t::muxer, &config);
        return execute_app(fx_dir, &init, new_argc, new_argv);
    }
    else
    {
        trace::verbose(_X("Executing as a standalone app as per config file [%s]"), config_file.c_str());
        pal::string_t impl_dir = get_directory(app_or_deps);
        if (!library_exists_in_dir(impl_dir, LIBHOSTPOLICY_NAME, nullptr) && !probe_paths.empty() && !deps_file.empty())
        {
            bool found = false;
            pal::string_t candidate = impl_dir;
            deps_json_t deps_json(false, deps_file);
            for (const auto& probe_path : probe_paths)
            {
                trace::verbose(_X("Considering %s for hostpolicy library"), probe_path.c_str());
                if (deps_json.is_valid() &&
                    deps_json.has_hostpolicy_entry() &&
                    deps_json.get_hostpolicy_entry().to_full_path(probe_path, &candidate))
                {
                    found = true; // candidate contains the right path.
                    break;
                }
            }
            if (!found)
            {
                trace::error(_X("Policy library either not found in deps [%s] or not found in %d probe paths."), deps_file.c_str(), probe_paths.size());
                return StatusCode::CoreHostLibMissingFailure;
            }
            impl_dir = get_directory(candidate);
        }
        corehost_init_t init(deps_file, probe_paths, _X(""), host_mode_t::muxer, &config);
        return execute_app(impl_dir, &init, new_argc, new_argv);
    }
}
Esempio n. 2
0
int fx_muxer_t::read_config_and_execute(
    const pal::string_t& own_dir, 
    const pal::string_t& app_candidate,
    const std::unordered_map<pal::string_t, std::vector<pal::string_t>>& opts,
    int new_argc, const pal::char_t** new_argv, host_mode_t mode)
{
    pal::string_t opts_fx_version = _X("--fx-version");
    pal::string_t opts_deps_file = _X("--depsfile");
    pal::string_t opts_probe_path = _X("--additionalprobingpath");
    pal::string_t opts_runtime_config = _X("--runtimeconfig");

    pal::string_t fx_version = get_last_known_arg(opts, opts_fx_version, _X(""));
    pal::string_t deps_file = get_last_known_arg(opts, opts_deps_file, _X(""));
    pal::string_t runtime_config = get_last_known_arg(opts, opts_runtime_config, _X(""));
    std::vector<pal::string_t> spec_probe_paths = opts.count(opts_probe_path) ? opts.find(opts_probe_path)->second : std::vector<pal::string_t>();

    if (!deps_file.empty() && (!pal::realpath(&deps_file) || !pal::file_exists(deps_file)))
    {
        trace::error(_X("The specified deps.json [%s] does not exist"), deps_file.c_str());
        return StatusCode::InvalidArgFailure;
    }
    if (!runtime_config.empty() && (!pal::realpath(&runtime_config) || !pal::file_exists(runtime_config)))
    {
        trace::error(_X("The specified runtimeconfig.json [%s] does not exist"), runtime_config.c_str());
        return StatusCode::InvalidConfigFile;
    }

    pal::string_t config_file, dev_config_file;

    if (runtime_config.empty())
    {
        trace::verbose(_X("App runtimeconfig.json from [%s]"), app_candidate.c_str());
        get_runtime_config_paths_from_app(app_candidate, &config_file, &dev_config_file);
    }
    else
    {
        trace::verbose(_X("Specified runtimeconfig.json from [%s]"), runtime_config.c_str());
        get_runtime_config_paths_from_arg(runtime_config, &config_file, &dev_config_file);
    }

    runtime_config_t config(config_file, dev_config_file);
    if (!config.is_valid())
    {
        trace::error(_X("Invalid runtimeconfig.json [%s] [%s]"), config.get_path().c_str(), config.get_dev_path().c_str());
        return StatusCode::InvalidConfigFile;
    }

    // Append specified probe paths first and then config file probe paths into realpaths.
    std::vector<pal::string_t> probe_realpaths;
    for (const auto& path : spec_probe_paths)
    {
        append_realpath(path, &probe_realpaths);
    }
    for (const auto& path : config.get_probe_paths())
    {
        append_realpath(path, &probe_realpaths);
    }

    bool is_portable = config.get_portable();
    pal::string_t fx_dir = is_portable ? resolve_fx_dir(mode, own_dir, config, fx_version) : _X("");

    trace::verbose(_X("Executing as a %s app as per config file [%s]"),
        (is_portable ? _X("portable") : _X("standalone")), config_file.c_str());

    pal::string_t impl_dir;
    if (!resolve_hostpolicy_dir(mode, own_dir, fx_dir, app_candidate, deps_file, fx_version, probe_realpaths, config, &impl_dir))
    {
        return CoreHostLibMissingFailure;
    }

    corehost_init_t init(deps_file, probe_realpaths, fx_dir, mode, config);
    return execute_app(impl_dir, &init, new_argc, new_argv);
}