summaryrefslogtreecommitdiff
path: root/src/node_process.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/node_process.cc')
-rw-r--r--src/node_process.cc227
1 files changed, 227 insertions, 0 deletions
diff --git a/src/node_process.cc b/src/node_process.cc
index d816c32f8d..8db1ab5ec0 100644
--- a/src/node_process.cc
+++ b/src/node_process.cc
@@ -25,23 +25,38 @@ typedef int mode_t;
#include <grp.h> // getgrnam()
#endif
+#ifdef __APPLE__
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
+#elif !defined(_MSC_VER)
+extern char **environ;
+#endif
+
namespace node {
using v8::Array;
using v8::ArrayBuffer;
using v8::BigUint64Array;
+using v8::Boolean;
+using v8::Context;
using v8::Float64Array;
+using v8::Function;
using v8::FunctionCallbackInfo;
using v8::HeapStatistics;
using v8::Integer;
using v8::Isolate;
using v8::Local;
+using v8::Name;
using v8::Number;
+using v8::PropertyCallbackInfo;
using v8::String;
using v8::Uint32;
using v8::Uint32Array;
using v8::Value;
+Mutex process_mutex;
+Mutex environ_mutex;
+
// Microseconds in a second, as a float, used in CPUUsage() below
#define MICROS_PER_SEC 1e6
// used in Hrtime() below
@@ -557,4 +572,216 @@ void InitGroups(const FunctionCallbackInfo<Value>& args) {
#endif // __POSIX__ && !defined(__ANDROID__) && !defined(__CloudABI__)
+void ProcessTitleGetter(Local<Name> property,
+ const PropertyCallbackInfo<Value>& info) {
+ char buffer[512];
+ uv_get_process_title(buffer, sizeof(buffer));
+ info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), buffer,
+ v8::NewStringType::kNormal).ToLocalChecked());
+}
+
+
+void ProcessTitleSetter(Local<Name> property,
+ Local<Value> value,
+ const PropertyCallbackInfo<void>& info) {
+ node::Utf8Value title(info.GetIsolate(), value);
+ TRACE_EVENT_METADATA1("__metadata", "process_name", "name",
+ TRACE_STR_COPY(*title));
+ uv_set_process_title(*title);
+}
+
+void EnvGetter(Local<Name> property,
+ const PropertyCallbackInfo<Value>& info) {
+ Isolate* isolate = info.GetIsolate();
+ if (property->IsSymbol()) {
+ return info.GetReturnValue().SetUndefined();
+ }
+ Mutex::ScopedLock lock(environ_mutex);
+#ifdef __POSIX__
+ node::Utf8Value key(isolate, property);
+ const char* val = getenv(*key);
+ if (val) {
+ return info.GetReturnValue().Set(String::NewFromUtf8(isolate, val,
+ v8::NewStringType::kNormal).ToLocalChecked());
+ }
+#else // _WIN32
+ node::TwoByteValue key(isolate, property);
+ WCHAR buffer[32767]; // The maximum size allowed for environment variables.
+ SetLastError(ERROR_SUCCESS);
+ DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
+ buffer,
+ arraysize(buffer));
+ // If result >= sizeof buffer the buffer was too small. That should never
+ // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
+ // found.
+ if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
+ result < arraysize(buffer)) {
+ const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
+ Local<String> rc = String::NewFromTwoByte(isolate, two_byte_buffer);
+ return info.GetReturnValue().Set(rc);
+ }
+#endif
+}
+
+
+void EnvSetter(Local<Name> property,
+ Local<Value> value,
+ const PropertyCallbackInfo<Value>& info) {
+ Environment* env = Environment::GetCurrent(info);
+ if (env->options()->pending_deprecation && env->EmitProcessEnvWarning() &&
+ !value->IsString() && !value->IsNumber() && !value->IsBoolean()) {
+ if (ProcessEmitDeprecationWarning(
+ env,
+ "Assigning any value other than a string, number, or boolean to a "
+ "process.env property is deprecated. Please make sure to convert the "
+ "value to a string before setting process.env with it.",
+ "DEP0104").IsNothing())
+ return;
+ }
+
+ Mutex::ScopedLock lock(environ_mutex);
+#ifdef __POSIX__
+ node::Utf8Value key(info.GetIsolate(), property);
+ node::Utf8Value val(info.GetIsolate(), value);
+ setenv(*key, *val, 1);
+#else // _WIN32
+ node::TwoByteValue key(info.GetIsolate(), property);
+ node::TwoByteValue val(info.GetIsolate(), value);
+ WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
+ // Environment variables that start with '=' are read-only.
+ if (key_ptr[0] != L'=') {
+ SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
+ }
+#endif
+ // Whether it worked or not, always return value.
+ info.GetReturnValue().Set(value);
+}
+
+
+void EnvQuery(Local<Name> property, const PropertyCallbackInfo<Integer>& info) {
+ Mutex::ScopedLock lock(environ_mutex);
+ int32_t rc = -1; // Not found unless proven otherwise.
+ if (property->IsString()) {
+#ifdef __POSIX__
+ node::Utf8Value key(info.GetIsolate(), property);
+ if (getenv(*key))
+ rc = 0;
+#else // _WIN32
+ node::TwoByteValue key(info.GetIsolate(), property);
+ WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
+ SetLastError(ERROR_SUCCESS);
+ if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
+ GetLastError() == ERROR_SUCCESS) {
+ rc = 0;
+ if (key_ptr[0] == L'=') {
+ // Environment variables that start with '=' are hidden and read-only.
+ rc = static_cast<int32_t>(v8::ReadOnly) |
+ static_cast<int32_t>(v8::DontDelete) |
+ static_cast<int32_t>(v8::DontEnum);
+ }
+ }
+#endif
+ }
+ if (rc != -1)
+ info.GetReturnValue().Set(rc);
+}
+
+
+void EnvDeleter(Local<Name> property,
+ const PropertyCallbackInfo<Boolean>& info) {
+ Mutex::ScopedLock lock(environ_mutex);
+ if (property->IsString()) {
+#ifdef __POSIX__
+ node::Utf8Value key(info.GetIsolate(), property);
+ unsetenv(*key);
+#else
+ node::TwoByteValue key(info.GetIsolate(), property);
+ WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
+ SetEnvironmentVariableW(key_ptr, nullptr);
+#endif
+ }
+
+ // process.env never has non-configurable properties, so always
+ // return true like the tc39 delete operator.
+ info.GetReturnValue().Set(true);
+}
+
+
+void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
+ Environment* env = Environment::GetCurrent(info);
+ Isolate* isolate = env->isolate();
+ Local<Context> ctx = env->context();
+ Local<Function> fn = env->push_values_to_array_function();
+ Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
+ size_t idx = 0;
+
+ Mutex::ScopedLock lock(environ_mutex);
+#ifdef __POSIX__
+ int size = 0;
+ while (environ[size])
+ size++;
+
+ Local<Array> envarr = Array::New(isolate);
+
+ for (int i = 0; i < size; ++i) {
+ const char* var = environ[i];
+ const char* s = strchr(var, '=');
+ const int length = s ? s - var : strlen(var);
+ argv[idx] = String::NewFromUtf8(isolate,
+ var,
+ v8::NewStringType::kNormal,
+ length).ToLocalChecked();
+ if (++idx >= arraysize(argv)) {
+ fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
+ idx = 0;
+ }
+ }
+ if (idx > 0) {
+ fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
+ }
+#else // _WIN32
+ WCHAR* environment = GetEnvironmentStringsW();
+ if (environment == nullptr)
+ return; // This should not happen.
+ Local<Array> envarr = Array::New(isolate);
+ WCHAR* p = environment;
+ while (*p) {
+ WCHAR* s;
+ if (*p == L'=') {
+ // If the key starts with '=' it is a hidden environment variable.
+ p += wcslen(p) + 1;
+ continue;
+ } else {
+ s = wcschr(p, L'=');
+ }
+ if (!s) {
+ s = p + wcslen(p);
+ }
+ const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
+ const size_t two_byte_buffer_len = s - p;
+ argv[idx] = String::NewFromTwoByte(isolate,
+ two_byte_buffer,
+ String::kNormalString,
+ two_byte_buffer_len);
+ if (++idx >= arraysize(argv)) {
+ fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
+ idx = 0;
+ }
+ p = s + wcslen(s) + 1;
+ }
+ if (idx > 0) {
+ fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
+ }
+ FreeEnvironmentStringsW(environment);
+#endif
+
+ info.GetReturnValue().Set(envarr);
+}
+
+void GetParentProcessId(Local<Name> property,
+ const PropertyCallbackInfo<Value>& info) {
+ info.GetReturnValue().Set(Integer::New(info.GetIsolate(), uv_os_getppid()));
+}
+
+
} // namespace node