mirror of
https://github.com/neovim/neovim.git
synced 2025-09-13 06:48:17 +00:00
Add os_getfullenv_size/os_copyfullenv
This commit is contained in:
@@ -272,15 +272,6 @@ static void close_cb(Stream *stream, void *data)
|
|||||||
channel_decref(data);
|
channel_decref(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void free_env(char **env)
|
|
||||||
{
|
|
||||||
if (!env) { return; }
|
|
||||||
for (char **it = env; *it; it++) {
|
|
||||||
XFREE_CLEAR(*it);
|
|
||||||
}
|
|
||||||
xfree(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Starts a job and returns the associated channel
|
/// Starts a job and returns the associated channel
|
||||||
///
|
///
|
||||||
@@ -362,7 +353,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
|
|||||||
if (status) {
|
if (status) {
|
||||||
EMSG3(_(e_jobspawn), os_strerror(status), cmd);
|
EMSG3(_(e_jobspawn), os_strerror(status), cmd);
|
||||||
xfree(cmd);
|
xfree(cmd);
|
||||||
free_env(proc->env);
|
os_free_fullenv(proc->env);
|
||||||
if (proc->type == kProcessTypePty) {
|
if (proc->type == kProcessTypePty) {
|
||||||
xfree(chan->stream.pty.term_name);
|
xfree(chan->stream.pty.term_name);
|
||||||
}
|
}
|
||||||
@@ -371,7 +362,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
xfree(cmd);
|
xfree(cmd);
|
||||||
free_env(proc->env);
|
os_free_fullenv(proc->env);
|
||||||
|
|
||||||
|
|
||||||
wstream_init(&proc->in, 0);
|
wstream_init(&proc->in, 0);
|
||||||
|
@@ -8716,18 +8716,25 @@ static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
{
|
{
|
||||||
tv_dict_alloc_ret(rettv);
|
tv_dict_alloc_ret(rettv);
|
||||||
|
|
||||||
for (int i = 0; ; i++) {
|
size_t env_size = os_get_fullenv_size();
|
||||||
// TODO(justinmk): use os_copyfullenv from #7202 ?
|
char **env = xmalloc(sizeof(*env) * (env_size + 1));
|
||||||
char *envname = os_getenvname_at_index((size_t)i);
|
env[env_size] = NULL;
|
||||||
if (envname == NULL) {
|
|
||||||
break;
|
os_copy_fullenv(env, env_size);
|
||||||
}
|
|
||||||
const char *value = os_getenv(envname);
|
for (size_t i = 0; i < env_size; i++) {
|
||||||
|
const char * str = env[i];
|
||||||
|
const char * const end = strchr(str + (str[0] == '=' ? 1 : 0),
|
||||||
|
'=');
|
||||||
|
assert(end != NULL);
|
||||||
|
ptrdiff_t len = end - str;
|
||||||
|
assert(len > 0);
|
||||||
|
const char * value = str + len + 1;
|
||||||
tv_dict_add_str(rettv->vval.v_dict,
|
tv_dict_add_str(rettv->vval.v_dict,
|
||||||
(char *)envname, STRLEN((char *)envname),
|
str, len,
|
||||||
value == NULL ? "" : value);
|
value);
|
||||||
xfree(envname);
|
|
||||||
}
|
}
|
||||||
|
os_free_fullenv(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -12639,15 +12646,12 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
env = xmalloc((custom_env_size + 1) * sizeof(*env));
|
env = xmalloc((custom_env_size + 1) * sizeof(*env));
|
||||||
env_size = 0;
|
env_size = 0;
|
||||||
} else {
|
} else {
|
||||||
char **genv = os_getfullenv();
|
env_size = os_get_fullenv_size();
|
||||||
for (env = genv; *env; env++) {
|
|
||||||
env_size++;
|
|
||||||
}
|
|
||||||
env = xmalloc((custom_env_size + env_size + 1) * sizeof(*env));
|
env = xmalloc((custom_env_size + env_size + 1) * sizeof(*env));
|
||||||
|
|
||||||
for (i = 0; i < env_size; i++) {
|
os_copy_fullenv(env, env_size);
|
||||||
env[i] = xstrdup(genv[i]);
|
i = env_size;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
assert(env); // env must be allocated at this point
|
assert(env); // env must be allocated at this point
|
||||||
|
|
||||||
|
@@ -184,39 +184,139 @@ int os_unsetenv(const char *name)
|
|||||||
return r == 0 ? 0 : -1;
|
return r == 0 ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char **os_getfullenv(void)
|
/// Returns number of variables in the current environment variables block
|
||||||
|
size_t os_get_fullenv_size(void)
|
||||||
{
|
{
|
||||||
|
size_t len = 0;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
wchar_t *env = GetEnvironmentStringsW();
|
wchar_t *envstrings = GetEnvironmentStringsW();
|
||||||
if (!env) {
|
wchar_t *p = envstrings;
|
||||||
return NULL;
|
size_t l;
|
||||||
|
if (!envstrings) {
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
char *name = NULL;
|
|
||||||
size_t current_index = 0;
|
|
||||||
// GetEnvironmentStringsW() result has this format:
|
// GetEnvironmentStringsW() result has this format:
|
||||||
// var1=value1\0var2=value2\0...varN=valueN\0\0
|
// var1=value1\0var2=value2\0...varN=valueN\0\0
|
||||||
for (wchar_t *it = env; *it != L'\0' || *(it + 1) != L'\0'; it++) {
|
while ((l = wcslen(p)) != 0) {
|
||||||
if (index == current_index) {
|
p += l + 1;
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeEnvironmentStringsW(envstrings);
|
||||||
|
#else
|
||||||
|
# if defined(HAVE__NSGETENVIRON)
|
||||||
|
char **environ = *_NSGetEnviron();
|
||||||
|
# else
|
||||||
|
extern char **environ;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
while (environ[len] != NULL) {
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void os_free_fullenv(char **env)
|
||||||
|
{
|
||||||
|
if (!env) { return; }
|
||||||
|
for (char **it = env; *it; it++) {
|
||||||
|
XFREE_CLEAR(*it);
|
||||||
|
}
|
||||||
|
xfree(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copies the current environment variables into the given array, `env`. Each
|
||||||
|
/// array element is of the form "NAME=VALUE".
|
||||||
|
/// Result must be freed by the caller.
|
||||||
|
///
|
||||||
|
/// @param[out] env array to populate with environment variables
|
||||||
|
/// @param env_size size of `env`, @see os_fullenv_size
|
||||||
|
void os_copy_fullenv(char **env, size_t env_size)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
wchar_t *envstrings = GetEnvironmentStringsW();
|
||||||
|
if (!envstrings) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wchar_t *p = envstrings;
|
||||||
|
size_t i = 0;
|
||||||
|
size_t l;
|
||||||
|
// GetEnvironmentStringsW() result has this format:
|
||||||
|
// var1=value1\0var2=value2\0...varN=valueN\0\0
|
||||||
|
while ((l = wcslen(p)) != 0 && i < env_size) {
|
||||||
|
char *utf8_str;
|
||||||
|
int conversion_result = utf16_to_utf8(p, -1, &utf8_str);
|
||||||
|
if (conversion_result != 0) {
|
||||||
|
EMSG2("utf16_to_utf8 failed: %d", conversion_result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p += l + 1;
|
||||||
|
|
||||||
|
env[i] = utf8_str;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeEnvironmentStringsW(envstrings);
|
||||||
|
#else
|
||||||
|
# if defined(HAVE__NSGETENVIRON)
|
||||||
|
char **environ = *_NSGetEnviron();
|
||||||
|
# else
|
||||||
|
extern char **environ;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (environ[i] != NULL && i < env_size) {
|
||||||
|
env[i] = xstrdup(environ[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy value of the environment variable at `index` in the current
|
||||||
|
/// environment variables block.
|
||||||
|
/// Result must be freed by the caller.
|
||||||
|
///
|
||||||
|
/// @param index nth item in environment variables block
|
||||||
|
/// @return [allocated] environment variable's value, or NULL
|
||||||
|
char *os_getenvname_at_index(size_t index)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
wchar_t *envstrings = GetEnvironmentStringsW();
|
||||||
|
if (!envstrings) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
wchar_t *p = envstrings;
|
||||||
|
char *name = NULL;
|
||||||
|
size_t i = 0;
|
||||||
|
size_t l;
|
||||||
|
// GetEnvironmentStringsW() result has this format:
|
||||||
|
// var1=value1\0var2=value2\0...varN=valueN\0\0
|
||||||
|
while ((l = wcslen(p)) != 0 && i <= index) {
|
||||||
|
if (i == index) {
|
||||||
char *utf8_str;
|
char *utf8_str;
|
||||||
int conversion_result = utf16_to_utf8(it, -1, &utf8_str);
|
int conversion_result = utf16_to_utf8(p, -1, &utf8_str);
|
||||||
if (conversion_result != 0) {
|
if (conversion_result != 0) {
|
||||||
EMSG2("utf16_to_utf8 failed: %d", conversion_result);
|
EMSG2("utf16_to_utf8 failed: %d", conversion_result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
size_t namesize = 0;
|
|
||||||
while (utf8_str[namesize] != '=' && utf8_str[namesize] != NUL) {
|
const char * const end = strchr(utf8_str, '=');
|
||||||
namesize++;
|
assert(end != NULL);
|
||||||
}
|
ptrdiff_t len = end - utf8_str;
|
||||||
name = (char *)vim_strnsave((char_u *)utf8_str, namesize);
|
assert(len > 0);
|
||||||
|
name = xstrndup(utf8_str, (size_t)len);
|
||||||
xfree(utf8_str);
|
xfree(utf8_str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (*it == L'\0') {
|
|
||||||
current_index++;
|
// Advance past the name and NUL
|
||||||
}
|
p += l + 1;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeEnvironmentStringsW(env);
|
FreeEnvironmentStringsW(envstrings);
|
||||||
return name;
|
return name;
|
||||||
#else
|
#else
|
||||||
# if defined(HAVE__NSGETENVIRON)
|
# if defined(HAVE__NSGETENVIRON)
|
||||||
@@ -224,26 +324,20 @@ char **os_getfullenv(void)
|
|||||||
# else
|
# else
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
# endif
|
# endif
|
||||||
return environ;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *os_getenvname_at_index(size_t index)
|
|
||||||
{
|
|
||||||
char **env = os_getfullenv();
|
|
||||||
// check if index is inside the environ array
|
// check if index is inside the environ array
|
||||||
for (size_t i = 0; i <= index; i++) {
|
for (size_t i = 0; i <= index; i++) {
|
||||||
if (env[i] == NULL) {
|
if (environ[i] == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
char *str = env[index];
|
char *str = environ[index];
|
||||||
assert(str != NULL);
|
assert(str != NULL);
|
||||||
size_t namesize = 0;
|
const char * const end = strchr(str, '=');
|
||||||
while (str[namesize] != '=' && str[namesize] != NUL) {
|
assert(end != NULL);
|
||||||
namesize++;
|
ptrdiff_t len = end - str;
|
||||||
}
|
assert(len > 0);
|
||||||
char *name = (char *)vim_strnsave((char_u *)str, namesize);
|
return xstrndup(str, (size_t)len);
|
||||||
return name;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user