unix,win: add ability to retrieve all env variables
Fixes: https://github.com/libuv/libuv/issues/2400 PR-URL: https://github.com/libuv/libuv/pull/2404 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
parent
ef218cede9
commit
2480b6158a
@ -180,6 +180,17 @@ Data types
|
|||||||
char machine[256];
|
char machine[256];
|
||||||
} uv_utsname_t;
|
} uv_utsname_t;
|
||||||
|
|
||||||
|
.. c:type:: uv_env_item_t
|
||||||
|
|
||||||
|
Data type for environment variable storage.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
typedef struct uv_env_item_s {
|
||||||
|
char* name;
|
||||||
|
char* value;
|
||||||
|
} uv_env_item_t;
|
||||||
|
|
||||||
|
|
||||||
API
|
API
|
||||||
---
|
---
|
||||||
@ -523,6 +534,23 @@ API
|
|||||||
|
|
||||||
.. versionadded:: 1.8.0
|
.. versionadded:: 1.8.0
|
||||||
|
|
||||||
|
.. c:function:: int uv_os_environ(uv_env_item_t** envitems, int* count)
|
||||||
|
|
||||||
|
Retrieves all environment variables. This function will allocate memory
|
||||||
|
which must be freed by calling :c:func:`uv_os_free_environ`.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
This function is not thread safe.
|
||||||
|
|
||||||
|
.. versionadded:: 1.31.0
|
||||||
|
|
||||||
|
.. c:function:: void uv_os_free_environ(uv_env_item_t* envitems, int count);
|
||||||
|
|
||||||
|
Frees the memory allocated for the environment variables by
|
||||||
|
:c:func:`uv_os_environ`.
|
||||||
|
|
||||||
|
.. versionadded:: 1.31.0
|
||||||
|
|
||||||
.. c:function:: int uv_os_getenv(const char* name, char* buffer, size_t* size)
|
.. c:function:: int uv_os_getenv(const char* name, char* buffer, size_t* size)
|
||||||
|
|
||||||
Retrieves the environment variable specified by `name`, copies its value
|
Retrieves the environment variable specified by `name`, copies its value
|
||||||
|
|||||||
@ -231,6 +231,7 @@ typedef struct uv_fs_s uv_fs_t;
|
|||||||
typedef struct uv_work_s uv_work_t;
|
typedef struct uv_work_s uv_work_t;
|
||||||
|
|
||||||
/* None of the above. */
|
/* None of the above. */
|
||||||
|
typedef struct uv_env_item_s uv_env_item_t;
|
||||||
typedef struct uv_cpu_info_s uv_cpu_info_t;
|
typedef struct uv_cpu_info_s uv_cpu_info_t;
|
||||||
typedef struct uv_interface_address_s uv_interface_address_t;
|
typedef struct uv_interface_address_s uv_interface_address_t;
|
||||||
typedef struct uv_dirent_s uv_dirent_t;
|
typedef struct uv_dirent_s uv_dirent_t;
|
||||||
@ -1162,6 +1163,13 @@ UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
|
|||||||
UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||||
int count);
|
int count);
|
||||||
|
|
||||||
|
struct uv_env_item_s {
|
||||||
|
char* name;
|
||||||
|
char* value;
|
||||||
|
};
|
||||||
|
|
||||||
|
UV_EXTERN int uv_os_environ(uv_env_item_t** envitems, int* count);
|
||||||
|
UV_EXTERN void uv_os_free_environ(uv_env_item_t* envitems, int count);
|
||||||
UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size);
|
UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size);
|
||||||
UV_EXTERN int uv_os_setenv(const char* name, const char* value);
|
UV_EXTERN int uv_os_setenv(const char* name, const char* value);
|
||||||
UV_EXTERN int uv_os_unsetenv(const char* name);
|
UV_EXTERN int uv_os_unsetenv(const char* name);
|
||||||
|
|||||||
@ -50,11 +50,15 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
# include <crt_externs.h>
|
||||||
# include <mach-o/dyld.h> /* _NSGetExecutablePath */
|
# include <mach-o/dyld.h> /* _NSGetExecutablePath */
|
||||||
# include <sys/filio.h>
|
# include <sys/filio.h>
|
||||||
# if defined(O_CLOEXEC)
|
# if defined(O_CLOEXEC)
|
||||||
# define UV__O_CLOEXEC O_CLOEXEC
|
# define UV__O_CLOEXEC O_CLOEXEC
|
||||||
# endif
|
# endif
|
||||||
|
# define environ (*_NSGetEnviron())
|
||||||
|
#else
|
||||||
|
extern char** environ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__DragonFly__) || \
|
#if defined(__DragonFly__) || \
|
||||||
@ -1284,6 +1288,62 @@ int uv_translate_sys_error(int sys_errno) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_os_environ(uv_env_item_t** envitems, int* count) {
|
||||||
|
int i, j, cnt;
|
||||||
|
uv_env_item_t* envitem;
|
||||||
|
|
||||||
|
*envitems = NULL;
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
for (i = 0; environ[i] != NULL; i++);
|
||||||
|
|
||||||
|
*envitems = uv__calloc(i, sizeof(**envitems));
|
||||||
|
|
||||||
|
if (envitems == NULL)
|
||||||
|
return UV_ENOMEM;
|
||||||
|
|
||||||
|
for (j = 0, cnt = 0; j < i; j++) {
|
||||||
|
char* buf;
|
||||||
|
char* ptr;
|
||||||
|
|
||||||
|
if (environ[j] == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
buf = uv__strdup(environ[j]);
|
||||||
|
if (buf == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ptr = strchr(buf, '=');
|
||||||
|
if (ptr == NULL) {
|
||||||
|
uv__free(buf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
envitem = &(*envitems)[cnt];
|
||||||
|
envitem->name = buf;
|
||||||
|
envitem->value = ptr + 1;
|
||||||
|
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*count = cnt;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
for (i = 0; i < cnt; i++) {
|
||||||
|
envitem = &(*envitems)[cnt];
|
||||||
|
uv__free(envitem->name);
|
||||||
|
}
|
||||||
|
uv__free(*envitems);
|
||||||
|
|
||||||
|
*envitems = NULL;
|
||||||
|
*count = 0;
|
||||||
|
return UV_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_os_getenv(const char* name, char* buffer, size_t* size) {
|
int uv_os_getenv(const char* name, char* buffer, size_t* size) {
|
||||||
char* var;
|
char* var;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|||||||
@ -786,3 +786,14 @@ void uv_loop_delete(uv_loop_t* loop) {
|
|||||||
if (loop != default_loop)
|
if (loop != default_loop)
|
||||||
uv__free(loop);
|
uv__free(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void uv_os_free_environ(uv_env_item_t* envitems, int count) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
uv__free(envitems[i].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
uv__free(envitems);
|
||||||
|
}
|
||||||
|
|||||||
@ -1397,6 +1397,75 @@ int uv_os_get_passwd(uv_passwd_t* pwd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_os_environ(uv_env_item_t** envitems, int* count) {
|
||||||
|
wchar_t* env;
|
||||||
|
wchar_t* penv;
|
||||||
|
int i, cnt;
|
||||||
|
uv_env_item_t* envitem;
|
||||||
|
|
||||||
|
*envitems = NULL;
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
env = GetEnvironmentStringsW();
|
||||||
|
if (env == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (penv = env, i = 0; *penv != L'\0'; penv += wcslen(penv) + 1, i++);
|
||||||
|
|
||||||
|
*envitems = uv__calloc(i, sizeof(**envitems));
|
||||||
|
if (envitems == NULL) {
|
||||||
|
FreeEnvironmentStringsW(env);
|
||||||
|
return UV_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
penv = env;
|
||||||
|
cnt = 0;
|
||||||
|
|
||||||
|
while (*penv != L'\0' && cnt < i) {
|
||||||
|
char* buf;
|
||||||
|
char* ptr;
|
||||||
|
|
||||||
|
if (uv__convert_utf16_to_utf8(penv, -1, &buf) != 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ptr = strchr(buf, '=');
|
||||||
|
if (ptr == NULL) {
|
||||||
|
uv__free(buf);
|
||||||
|
goto do_continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
envitem = &(*envitems)[cnt];
|
||||||
|
envitem->name = buf;
|
||||||
|
envitem->value = ptr + 1;
|
||||||
|
|
||||||
|
cnt++;
|
||||||
|
|
||||||
|
do_continue:
|
||||||
|
penv += wcslen(penv) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeEnvironmentStringsW(env);
|
||||||
|
|
||||||
|
*count = cnt;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
FreeEnvironmentStringsW(env);
|
||||||
|
|
||||||
|
for (i = 0; i < cnt; i++) {
|
||||||
|
envitem = &(*envitems)[cnt];
|
||||||
|
uv__free(envitem->name);
|
||||||
|
}
|
||||||
|
uv__free(*envitems);
|
||||||
|
|
||||||
|
*envitems = NULL;
|
||||||
|
*count = 0;
|
||||||
|
return UV_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_os_getenv(const char* name, char* buffer, size_t* size) {
|
int uv_os_getenv(const char* name, char* buffer, size_t* size) {
|
||||||
wchar_t var[MAX_ENV_VAR_LENGTH];
|
wchar_t var[MAX_ENV_VAR_LENGTH];
|
||||||
wchar_t* name_w;
|
wchar_t* name_w;
|
||||||
|
|||||||
@ -27,9 +27,11 @@
|
|||||||
|
|
||||||
TEST_IMPL(env_vars) {
|
TEST_IMPL(env_vars) {
|
||||||
const char* name = "UV_TEST_FOO";
|
const char* name = "UV_TEST_FOO";
|
||||||
|
const char* name2 = "UV_TEST_FOO2";
|
||||||
char buf[BUF_SIZE];
|
char buf[BUF_SIZE];
|
||||||
size_t size;
|
size_t size;
|
||||||
int r;
|
int i, r, envcount, found;
|
||||||
|
uv_env_item_t* envitems;
|
||||||
|
|
||||||
/* Reject invalid inputs when setting an environment variable */
|
/* Reject invalid inputs when setting an environment variable */
|
||||||
r = uv_os_setenv(NULL, "foo");
|
r = uv_os_setenv(NULL, "foo");
|
||||||
@ -86,5 +88,38 @@ TEST_IMPL(env_vars) {
|
|||||||
r = uv_os_unsetenv(name);
|
r = uv_os_unsetenv(name);
|
||||||
ASSERT(r == 0);
|
ASSERT(r == 0);
|
||||||
|
|
||||||
|
/* Check getting all env variables. */
|
||||||
|
r = uv_os_setenv(name, "123456789");
|
||||||
|
ASSERT(r == 0);
|
||||||
|
r = uv_os_setenv(name2, "");
|
||||||
|
ASSERT(r == 0);
|
||||||
|
|
||||||
|
r = uv_os_environ(&envitems, &envcount);
|
||||||
|
ASSERT(r == 0);
|
||||||
|
ASSERT(envcount > 0);
|
||||||
|
|
||||||
|
found = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < envcount; i++) {
|
||||||
|
/* printf("Env: %s = %s\n", envitems[i].name, envitems[i].value); */
|
||||||
|
if (strcmp(envitems[i].name, name) == 0) {
|
||||||
|
found++;
|
||||||
|
ASSERT(strcmp(envitems[i].value, "123456789") == 0);
|
||||||
|
} else if (strcmp(envitems[i].name, name2) == 0) {
|
||||||
|
found++;
|
||||||
|
ASSERT(strlen(envitems[i].value) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(found == 2);
|
||||||
|
|
||||||
|
uv_os_free_environ(envitems, envcount);
|
||||||
|
|
||||||
|
r = uv_os_unsetenv(name);
|
||||||
|
ASSERT(r == 0);
|
||||||
|
|
||||||
|
r = uv_os_unsetenv(name2);
|
||||||
|
ASSERT(r == 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user