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];
|
||||
} 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
|
||||
---
|
||||
@ -523,6 +534,23 @@ API
|
||||
|
||||
.. 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)
|
||||
|
||||
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;
|
||||
|
||||
/* 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_interface_address_s uv_interface_address_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,
|
||||
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_setenv(const char* name, const char* value);
|
||||
UV_EXTERN int uv_os_unsetenv(const char* name);
|
||||
|
||||
@ -50,11 +50,15 @@
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <crt_externs.h>
|
||||
# include <mach-o/dyld.h> /* _NSGetExecutablePath */
|
||||
# include <sys/filio.h>
|
||||
# if defined(O_CLOEXEC)
|
||||
# define UV__O_CLOEXEC O_CLOEXEC
|
||||
# endif
|
||||
# define environ (*_NSGetEnviron())
|
||||
#else
|
||||
extern char** environ;
|
||||
#endif
|
||||
|
||||
#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) {
|
||||
char* var;
|
||||
size_t len;
|
||||
|
||||
@ -786,3 +786,14 @@ void uv_loop_delete(uv_loop_t* loop) {
|
||||
if (loop != default_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) {
|
||||
wchar_t var[MAX_ENV_VAR_LENGTH];
|
||||
wchar_t* name_w;
|
||||
|
||||
@ -27,9 +27,11 @@
|
||||
|
||||
TEST_IMPL(env_vars) {
|
||||
const char* name = "UV_TEST_FOO";
|
||||
const char* name2 = "UV_TEST_FOO2";
|
||||
char buf[BUF_SIZE];
|
||||
size_t size;
|
||||
int r;
|
||||
int i, r, envcount, found;
|
||||
uv_env_item_t* envitems;
|
||||
|
||||
/* Reject invalid inputs when setting an environment variable */
|
||||
r = uv_os_setenv(NULL, "foo");
|
||||
@ -86,5 +88,38 @@ TEST_IMPL(env_vars) {
|
||||
r = uv_os_unsetenv(name);
|
||||
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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user