diff --git a/src/node.cc b/src/node.cc index acffc1cc119e90..a0398b1a4f8d2c 100644 --- a/src/node.cc +++ b/src/node.cc @@ -790,80 +790,19 @@ int InitializeNodeWithArgs(std::vector* argv, V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1); #endif - std::shared_ptr default_env_options = - per_process::cli_options->per_isolate->per_env; - { - std::string text; - default_env_options->pending_deprecation = - credentials::SafeGetenv("NODE_PENDING_DEPRECATION", &text) && - text[0] == '1'; - } - - // Allow for environment set preserving symlinks. - { - std::string text; - default_env_options->preserve_symlinks = - credentials::SafeGetenv("NODE_PRESERVE_SYMLINKS", &text) && - text[0] == '1'; - } - - { - std::string text; - default_env_options->preserve_symlinks_main = - credentials::SafeGetenv("NODE_PRESERVE_SYMLINKS_MAIN", &text) && - text[0] == '1'; - } - - if (default_env_options->redirect_warnings.empty()) { - credentials::SafeGetenv("NODE_REDIRECT_WARNINGS", - &default_env_options->redirect_warnings); - } + HandleEnvOptions(per_process::cli_options->per_isolate->per_env); #if !defined(NODE_WITHOUT_NODE_OPTIONS) std::string node_options; if (credentials::SafeGetenv("NODE_OPTIONS", &node_options)) { - std::vector env_argv; - // [0] is expected to be the program name, fill it in from the real argv. - env_argv.push_back(argv->at(0)); - - bool is_in_string = false; - bool will_start_new_arg = true; - for (std::string::size_type index = 0; - index < node_options.size(); - ++index) { - char c = node_options.at(index); - - // Backslashes escape the following character - if (c == '\\' && is_in_string) { - if (index + 1 == node_options.size()) { - errors->push_back("invalid value for NODE_OPTIONS " - "(invalid escape)\n"); - return 9; - } else { - c = node_options.at(++index); - } - } else if (c == ' ' && !is_in_string) { - will_start_new_arg = true; - continue; - } else if (c == '"') { - is_in_string = !is_in_string; - continue; - } + std::vector env_argv = + ParseNodeOptionsEnvVar(node_options, errors); - if (will_start_new_arg) { - env_argv.emplace_back(std::string(1, c)); - will_start_new_arg = false; - } else { - env_argv.back() += c; - } - } + if (!errors->empty()) return 9; - if (is_in_string) { - errors->push_back("invalid value for NODE_OPTIONS " - "(unterminated string)\n"); - return 9; - } + // [0] is expected to be the program name, fill it in from the real argv. + env_argv.insert(env_argv.begin(), argv->at(0)); const int exit_code = ProcessGlobalArgs(&env_argv, nullptr, diff --git a/src/node_options-inl.h b/src/node_options-inl.h index 8bb5b6155a21d1..885cb849744205 100644 --- a/src/node_options-inl.h +++ b/src/node_options-inl.h @@ -3,9 +3,9 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS +#include #include "node_options.h" #include "util.h" -#include namespace node { diff --git a/src/node_options.cc b/src/node_options.cc index 243e3a40cfaa4f..93f1e465e2610a 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -3,6 +3,7 @@ #include "env-inl.h" #include "node_binding.h" +#include "node_internals.h" #include #include @@ -1009,6 +1010,68 @@ void Initialize(Local target, } } // namespace options_parser + +void HandleEnvOptions(std::shared_ptr env_options) { + HandleEnvOptions(env_options, [](const char* name) { + std::string text; + return credentials::SafeGetenv(name, &text) ? text : ""; + }); +} + +void HandleEnvOptions(std::shared_ptr env_options, + std::function opt_getter) { + env_options->pending_deprecation = + opt_getter("NODE_PENDING_DEPRECATION") == "1"; + + env_options->preserve_symlinks = opt_getter("NODE_PRESERVE_SYMLINKS") == "1"; + + env_options->preserve_symlinks_main = + opt_getter("NODE_PRESERVE_SYMLINKS_MAIN") == "1"; + + if (env_options->redirect_warnings.empty()) + env_options->redirect_warnings = opt_getter("NODE_REDIRECT_WARNINGS"); +} + +std::vector ParseNodeOptionsEnvVar( + const std::string& node_options, std::vector* errors) { + std::vector env_argv; + + bool is_in_string = false; + bool will_start_new_arg = true; + for (std::string::size_type index = 0; index < node_options.size(); ++index) { + char c = node_options.at(index); + + // Backslashes escape the following character + if (c == '\\' && is_in_string) { + if (index + 1 == node_options.size()) { + errors->push_back("invalid value for NODE_OPTIONS " + "(invalid escape)\n"); + return env_argv; + } else { + c = node_options.at(++index); + } + } else if (c == ' ' && !is_in_string) { + will_start_new_arg = true; + continue; + } else if (c == '"') { + is_in_string = !is_in_string; + continue; + } + + if (will_start_new_arg) { + env_argv.emplace_back(std::string(1, c)); + will_start_new_arg = false; + } else { + env_argv.back() += c; + } + } + + if (is_in_string) { + errors->push_back("invalid value for NODE_OPTIONS " + "(unterminated string)\n"); + } + return env_argv; +} } // namespace node NODE_MODULE_CONTEXT_AWARE_INTERNAL(options, node::options_parser::Initialize) diff --git a/src/node_options.h b/src/node_options.h index f49d35cedad058..470007f06b6342 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -457,6 +457,13 @@ extern Mutex cli_options_mutex; extern std::shared_ptr cli_options; } // namespace per_process + +void HandleEnvOptions(std::shared_ptr env_options); +void HandleEnvOptions(std::shared_ptr env_options, + std::function opt_getter); + +std::vector ParseNodeOptionsEnvVar( + const std::string& node_options, std::vector* errors); } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS