Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
src: allow to reuse env options handling
  • Loading branch information
lundibundi committed Feb 10, 2020
commit 0c87f8cb1359139316b220a46f461a7923f037f8
73 changes: 6 additions & 67 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -790,80 +790,19 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1);
#endif

std::shared_ptr<EnvironmentOptions> 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<std::string> 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<std::string> 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,
Expand Down
2 changes: 1 addition & 1 deletion src/node_options-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include <cstdlib>
#include "node_options.h"
#include "util.h"
#include <cstdlib>

namespace node {

Expand Down
63 changes: 63 additions & 0 deletions src/node_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "env-inl.h"
#include "node_binding.h"
#include "node_internals.h"

#include <errno.h>
#include <sstream>
Expand Down Expand Up @@ -1009,6 +1010,68 @@ void Initialize(Local<Object> target,
}

} // namespace options_parser

void HandleEnvOptions(std::shared_ptr<EnvironmentOptions> env_options) {
HandleEnvOptions(env_options, [](const char* name) {
std::string text;
return credentials::SafeGetenv(name, &text) ? text : "";
});
}

void HandleEnvOptions(std::shared_ptr<EnvironmentOptions> env_options,
std::function<std::string(const char*)> opt_getter) {
Comment thread
lundibundi marked this conversation as resolved.
Resolved
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<std::string> ParseNodeOptionsEnvVar(
const std::string& node_options, std::vector<std::string>* errors) {
std::vector<std::string> 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)
7 changes: 7 additions & 0 deletions src/node_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,13 @@ extern Mutex cli_options_mutex;
extern std::shared_ptr<PerProcessOptions> cli_options;

} // namespace per_process

void HandleEnvOptions(std::shared_ptr<EnvironmentOptions> env_options);
void HandleEnvOptions(std::shared_ptr<EnvironmentOptions> env_options,
std::function<std::string(const char*)> opt_getter);

std::vector<std::string> ParseNodeOptionsEnvVar(
const std::string& node_options, std::vector<std::string>* errors);
} // namespace node

#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
Expand Down