|
|
@ -1296,7 +1296,8 @@ static Handle<Value> CwdForDrive(const Arguments& args) { |
|
|
|
env_key[1] = (WCHAR) drive; |
|
|
|
|
|
|
|
DWORD len = GetEnvironmentVariableW(env_key, NULL, 0); |
|
|
|
if (len == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) { |
|
|
|
if (len == 0 && (GetLastError() == ERROR_ENVVAR_NOT_FOUND || |
|
|
|
GetLastError() == ERROR_SUCCESS)) { |
|
|
|
// There is no current directory for that drive. Default to drive + ":\".
|
|
|
|
Local<String> cwd = String::Concat(String::New(&drive, 1), |
|
|
|
String::New(":\\")); |
|
|
@ -1317,7 +1318,7 @@ static Handle<Value> CwdForDrive(const Arguments& args) { |
|
|
|
} |
|
|
|
|
|
|
|
DWORD len2 = GetEnvironmentVariableW(env_key, buffer, len); |
|
|
|
if (len2 == 0 || len2 >= len) { |
|
|
|
if ((len2 == 0 && GetLastError() != ERROR_SUCCESS) || len2 >= len) { |
|
|
|
// Error
|
|
|
|
delete[] buffer; |
|
|
|
Local<Value> exception = Exception::Error( |
|
|
@ -1869,12 +1870,28 @@ static void ProcessTitleSetter(Local<String> property, |
|
|
|
|
|
|
|
static Handle<Value> EnvGetter(Local<String> property, |
|
|
|
const AccessorInfo& info) { |
|
|
|
HandleScope scope; |
|
|
|
#ifdef __POSIX__ |
|
|
|
String::Utf8Value key(property); |
|
|
|
const char* val = getenv(*key); |
|
|
|
if (val) { |
|
|
|
HandleScope scope; |
|
|
|
return scope.Close(String::New(val)); |
|
|
|
} |
|
|
|
#else // _WIN32
|
|
|
|
String::Value key(property); |
|
|
|
WCHAR buffer[32767]; // The maximum size allowed for environment variables.
|
|
|
|
DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key), |
|
|
|
buffer, |
|
|
|
ARRAY_SIZE(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
|
|
|
|
// not found.
|
|
|
|
if ((result > 0 || GetLastError() == ERROR_SUCCESS) && |
|
|
|
result < ARRAY_SIZE(buffer)) { |
|
|
|
return scope.Close(String::New(reinterpret_cast<uint16_t*>(buffer), result)); |
|
|
|
} |
|
|
|
#endif |
|
|
|
// Not found
|
|
|
|
return Undefined(); |
|
|
|
} |
|
|
|
|
|
|
@ -1883,66 +1900,82 @@ static Handle<Value> EnvSetter(Local<String> property, |
|
|
|
Local<Value> value, |
|
|
|
const AccessorInfo& info) { |
|
|
|
HandleScope scope; |
|
|
|
#ifdef __POSIX__ |
|
|
|
String::Utf8Value key(property); |
|
|
|
String::Utf8Value val(value); |
|
|
|
|
|
|
|
#ifdef __POSIX__ |
|
|
|
setenv(*key, *val, 1); |
|
|
|
#else // __WIN32__
|
|
|
|
int n = key.length() + val.length() + 2; |
|
|
|
char* pair = new char[n]; |
|
|
|
snprintf(pair, n, "%s=%s", *key, *val); |
|
|
|
int r = _putenv(pair); |
|
|
|
if (r) { |
|
|
|
fprintf(stderr, "error putenv: '%s'\n", pair); |
|
|
|
#else // _WIN32
|
|
|
|
String::Value key(property); |
|
|
|
String::Value val(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)); |
|
|
|
} |
|
|
|
delete [] pair; |
|
|
|
#endif |
|
|
|
|
|
|
|
return value; |
|
|
|
// Whether it worked or not, always return rval.
|
|
|
|
return scope.Close(value); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static Handle<Integer> EnvQuery(Local<String> property, |
|
|
|
const AccessorInfo& info) { |
|
|
|
HandleScope scope; |
|
|
|
#ifdef __POSIX__ |
|
|
|
String::Utf8Value key(property); |
|
|
|
if (getenv(*key)) { |
|
|
|
HandleScope scope; |
|
|
|
return scope.Close(Integer::New(None)); |
|
|
|
} |
|
|
|
return Handle<Integer>(); |
|
|
|
#else // _WIN32
|
|
|
|
String::Value key(property); |
|
|
|
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key); |
|
|
|
if (GetEnvironmentVariableW(key_ptr, NULL, 0) > 0 || |
|
|
|
GetLastError() == ERROR_SUCCESS) { |
|
|
|
if (key_ptr[0] == L'=') { |
|
|
|
// Environment variables that start with '=' are hidden and read-only.
|
|
|
|
return scope.Close(Integer::New(v8::ReadOnly || |
|
|
|
v8::DontDelete || |
|
|
|
v8::DontEnum)); |
|
|
|
} else { |
|
|
|
return scope.Close(Integer::New(None)); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
// Not found
|
|
|
|
return scope.Close(Handle<Integer>()); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static Handle<Boolean> EnvDeleter(Local<String> property, |
|
|
|
const AccessorInfo& info) { |
|
|
|
HandleScope scope; |
|
|
|
|
|
|
|
String::Utf8Value key(property); |
|
|
|
|
|
|
|
if (getenv(*key)) { |
|
|
|
#ifdef __POSIX__ |
|
|
|
unsetenv(*key); // prototyped as `void unsetenv(const char*)` on some platforms
|
|
|
|
String::Utf8Value key(property); |
|
|
|
// prototyped as `void unsetenv(const char*)` on some platforms
|
|
|
|
if (unsetenv(*key) < 0) { |
|
|
|
// Deletion failed. Return true if the key wasn't there in the first place,
|
|
|
|
// false if it is still there.
|
|
|
|
return scope.Close(Boolean::New(getenv(*key) == NULL)); |
|
|
|
}; |
|
|
|
#else |
|
|
|
int n = key.length() + 2; |
|
|
|
char* pair = new char[n]; |
|
|
|
snprintf(pair, n, "%s=", *key); |
|
|
|
int r = _putenv(pair); |
|
|
|
if (r) { |
|
|
|
fprintf(stderr, "error unsetenv: '%s'\n", pair); |
|
|
|
String::Value key(property); |
|
|
|
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key); |
|
|
|
if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, NULL)) { |
|
|
|
// Deletion failed. Return true if the key wasn't there in the first place,
|
|
|
|
// false if it is still there.
|
|
|
|
bool rv = GetEnvironmentVariableW(key_ptr, NULL, NULL) == 0 && |
|
|
|
GetLastError() != ERROR_SUCCESS; |
|
|
|
return scope.Close(Boolean::New(rv)); |
|
|
|
} |
|
|
|
delete [] pair; |
|
|
|
#endif |
|
|
|
return True(); |
|
|
|
} |
|
|
|
|
|
|
|
return False(); |
|
|
|
// It worked
|
|
|
|
return v8::True(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static Handle<Array> EnvEnumerator(const AccessorInfo& info) { |
|
|
|
HandleScope scope; |
|
|
|
|
|
|
|
#ifdef __POSIX__ |
|
|
|
int size = 0; |
|
|
|
while (environ[size]) size++; |
|
|
|
|
|
|
@ -1954,7 +1987,32 @@ static Handle<Array> EnvEnumerator(const AccessorInfo& info) { |
|
|
|
const int length = s ? s - var : strlen(var); |
|
|
|
env->Set(i, String::New(var, length)); |
|
|
|
} |
|
|
|
|
|
|
|
#else // _WIN32
|
|
|
|
WCHAR* environment = GetEnvironmentStringsW(); |
|
|
|
if (environment == NULL) { |
|
|
|
// This should not happen.
|
|
|
|
return scope.Close(Handle<Array>()); |
|
|
|
} |
|
|
|
Local<Array> env = Array::New(); |
|
|
|
WCHAR* p = environment; |
|
|
|
int i = 0; |
|
|
|
while (*p != NULL) { |
|
|
|
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); |
|
|
|
} |
|
|
|
env->Set(i++, String::New(reinterpret_cast<uint16_t*>(p), s - p)); |
|
|
|
p = s + wcslen(s) + 1; |
|
|
|
} |
|
|
|
FreeEnvironmentStringsW(environment); |
|
|
|
#endif |
|
|
|
return scope.Close(env); |
|
|
|
} |
|
|
|
|
|
|
|