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.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 7be8a868bd..a791dca39c 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -46,7 +46,19 @@ bool os_env_exists(const char *name)
int os_setenv(const char *name, const char *value, int overwrite)
FUNC_ATTR_NONNULL_ALL
{
+#ifdef HAVE_SETENV
return setenv(name, value, overwrite);
+#elif defined(HAVE_PUTENV_S)
+ if (!overwrite && os_getenv(name) != NULL) {
+ return 0;
+ }
+ if (_putenv_s(name, value) == 0) {
+ return 0;
+ }
+ return -1;
+#else
+# error "This system has no implementation available for os_setenv()"
+#endif
}
/// Unset environment variable
@@ -141,6 +153,27 @@ void init_homedir(void)
char_u *var = (char_u *)os_getenv("HOME");
+#ifdef WIN32
+ // Typically, $HOME is not defined on Windows, unless the user has
+ // specifically defined it for Vim's sake. However, on Windows NT
+ // platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for
+ // each user. Try constructing $HOME from these.
+ if (var == NULL) {
+ const char *homedrive = os_getenv("HOMEDRIVE");
+ const char *homepath = os_getenv("HOMEPATH");
+ if (homepath == NULL) {
+ homepath = "\\";
+ }
+ if (homedrive != NULL && strlen(homedrive) + strlen(homepath) < MAXPATHL) {
+ snprintf((char *)NameBuff, MAXPATHL, "%s%s", homedrive, homepath);
+ if (NameBuff[0] != NUL) {
+ var = NameBuff;
+ vim_setenv("HOME", (char *)NameBuff);
+ }
+ }
+ }
+#endif
+
if (var != NULL) {
#ifdef UNIX
/*
@@ -415,6 +448,74 @@ static char *remove_tail(char *p, char *pend, char *name)
return pend;
}
+/// Iterate over colon-separated list
+///
+/// @note Environment variables must not be modified during iteration.
+///
+/// @param[in] val Value of the environment variable to iterate over.
+/// @param[in] iter Pointer used for iteration. Must be NULL on first
+/// iteration.
+/// @param[out] dir Location where pointer to the start of the current
+/// directory name should be saved. May be set to NULL.
+/// @param[out] len Location where current directory length should be saved.
+///
+/// @return Next iter argument value or NULL when iteration should stop.
+const void *vim_colon_env_iter(const char *const val,
+ const void *const iter,
+ const char **const dir,
+ size_t *const len)
+ FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ const char *varval = (const char *) iter;
+ if (varval == NULL) {
+ varval = val;
+ }
+ *dir = varval;
+ const char *const dirend = strchr(varval, ':');
+ if (dirend == NULL) {
+ *len = strlen(varval);
+ return NULL;
+ } else {
+ *len = (size_t) (dirend - varval);
+ return dirend + 1;
+ }
+}
+
+/// Iterate over colon-separated list in reverse order
+///
+/// @note Environment variables must not be modified during iteration.
+///
+/// @param[in] val Value of the environment variable to iterate over.
+/// @param[in] iter Pointer used for iteration. Must be NULL on first
+/// iteration.
+/// @param[out] dir Location where pointer to the start of the current
+/// directory name should be saved. May be set to NULL.
+/// @param[out] len Location where current directory length should be saved.
+///
+/// @return Next iter argument value or NULL when iteration should stop.
+const void *vim_colon_env_iter_rev(const char *const val,
+ const void *const iter,
+ const char **const dir,
+ size_t *const len)
+ FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ const char *varend = (const char *) iter;
+ if (varend == NULL) {
+ varend = val + strlen(val) - 1;
+ }
+ const size_t varlen = (size_t) (varend - val) + 1;
+ const char *const colon = xmemrchr(val, ':', varlen);
+ if (colon == NULL) {
+ *len = varlen;
+ *dir = val;
+ return NULL;
+ } else {
+ *dir = colon + 1;
+ *len = (size_t) (varend - colon);
+ return colon - 1;
+ }
+}
+
/// Vim's version of getenv().
/// Special handling of $HOME, $VIM and $VIMRUNTIME, allowing the user to
/// override the vim runtime directory at runtime. Also does ACP to 'enc'