aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os/env.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/os/env.c')
-rw-r--r--src/nvim/os/env.c64
1 files changed, 43 insertions, 21 deletions
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 8620c79069..5b1cb01976 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -13,9 +13,9 @@
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
+#include "nvim/cmdexpand_defs.h"
#include "nvim/eval.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/macros_defs.h"
@@ -25,8 +25,10 @@
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/version.h"
#include "nvim/vim_defs.h"
@@ -46,6 +48,10 @@
# include <sys/utsname.h>
#endif
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "os/env.c.generated.h"
+#endif
+
// Because `uv_os_getenv` requires allocating, we must manage a map to maintain
// the behavior of `os_getenv`.
static PMap(cstr_t) envmap = MAP_INIT;
@@ -55,8 +61,7 @@ static PMap(cstr_t) envmap = MAP_INIT;
const char *os_getenv(const char *name)
FUNC_ATTR_NONNULL_ALL
{
- char *e;
- size_t size = 64;
+ char *e = NULL;
if (name[0] == '\0') {
return NULL;
}
@@ -72,23 +77,31 @@ const char *os_getenv(const char *name)
}
pmap_del2(&envmap, name);
}
- e = xmalloc(size);
- r = uv_os_getenv(name, e, &size);
+#define INIT_SIZE 64
+ size_t size = INIT_SIZE;
+ char buf[INIT_SIZE];
+ r = uv_os_getenv(name, buf, &size);
if (r == UV_ENOBUFS) {
- e = xrealloc(e, size);
+ e = xmalloc(size);
r = uv_os_getenv(name, e, &size);
- }
- if (r != 0 || size == 0 || e[0] == '\0') {
- xfree(e);
+ if (r != 0 || size == 0 || e[0] == '\0') {
+ XFREE_CLEAR(e);
+ goto end;
+ }
+ } else if (r != 0 || size == 0 || buf[0] == '\0') {
e = NULL;
goto end;
+ } else {
+ // NB: `size` param of uv_os_getenv() includes the NUL-terminator,
+ // except when it does not include the NUL-terminator.
+ e = xmemdupz(buf, size);
}
pmap_put(cstr_t)(&envmap, xstrdup(name), e);
end:
if (r != 0 && r != UV_ENOENT && r != UV_UNKNOWN) {
ELOG("uv_os_getenv(%s) failed: %d %s", name, r, uv_err_name(r));
}
- return (e == NULL || size == 0 || e[0] == '\0') ? NULL : e;
+ return e;
}
/// Returns true if environment variable `name` is defined (even if empty).
@@ -507,6 +520,17 @@ void free_homedir(void)
xfree(homedir);
}
+void free_envmap(void)
+{
+ cstr_t name;
+ ptr_t e;
+ map_foreach(&envmap, name, e, {
+ xfree((char *)name);
+ xfree(e);
+ });
+ map_destroy(cstr_t, &envmap);
+}
+
#endif
/// Call expand_env() and store the result in an allocated string.
@@ -562,6 +586,9 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
bool copy_char;
bool mustfree; // var was allocated, need to free it later
bool at_start = true; // at start of a name
+#if defined(BACKSLASH_IN_FILENAME)
+ char *const save_dst = dst;
+#endif
int prefix_len = (prefix == NULL) ? 0 : (int)strlen(prefix);
@@ -572,7 +599,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
if (src[0] == '`' && src[1] == '=') {
var = src;
src += 2;
- (void)skip_expr(&src, NULL);
+ skip_expr(&src, NULL);
if (*src == '`') {
src++;
}
@@ -604,7 +631,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
while (c-- > 0 && *tail != NUL && *tail != '}') {
*var++ = *tail++;
}
- } else // NOLINT
+ } else
#endif
{
while (c-- > 0 && *tail != NUL && vim_isIDc((uint8_t)(*tail))) {
@@ -702,7 +729,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
// with it, skip a character
if (after_pathsep(dst, dst + c)
#if defined(BACKSLASH_IN_FILENAME)
- && dst[-1] != ':'
+ && (dst == save_dst || dst[-1] != ':')
#endif
&& vim_ispathsep(*tail)) {
tail++;
@@ -904,10 +931,7 @@ char *vim_getenv(const char *name)
// Don't do this when default_vimruntime_dir is non-empty.
char *vim_path = NULL;
if (vimruntime
-#ifdef HAVE_PATHDEF
- && *default_vimruntime_dir == NUL
-#endif
- ) {
+ && *default_vimruntime_dir == NUL) {
kos_env_path = os_getenv("VIM");
if (kos_env_path != NULL) {
vim_path = vim_version_dir(kos_env_path);
@@ -966,7 +990,6 @@ char *vim_getenv(const char *name)
assert(vim_path != exe_name);
}
-#ifdef HAVE_PATHDEF
// When there is a pathdef.c file we can use default_vim_dir and
// default_vimruntime_dir
if (vim_path == NULL) {
@@ -980,7 +1003,6 @@ char *vim_getenv(const char *name)
}
}
}
-#endif
// Set the environment variable, so that the new value can be found fast
// next time, and others can also use it (e.g. Perl).
@@ -1051,7 +1073,7 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si
size_t usedlen = 0;
size_t flen = strlen(homedir_env_mod);
char *fbuf = NULL;
- (void)modify_fname(":p", false, &usedlen, &homedir_env_mod, &fbuf, &flen);
+ modify_fname(":p", false, &usedlen, &homedir_env_mod, &fbuf, &flen);
flen = strlen(homedir_env_mod);
assert(homedir_env_mod != homedir_env);
if (vim_ispathsep(homedir_env_mod[flen - 1])) {