mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +00:00 
			
		
		
		
	fix(env.c): drop envmap, free os_getenv() result #32683
Problem: vim.uv.os_setenv gets "stuck" per-key. #32550 Caused by the internal `envmap` cache. #7920 :echo $FOO <-- prints nothing :lua vim.uv.os_setenv("FOO", "bar") :echo $FOO <-- prints bar (as expected) :lua vim.uv.os_setenv("FOO", "fizz") :echo $FOO <-- prints bar, still (not expected. Should be "fizz") :lua vim.uv.os_unsetenv("FOO") :echo $FOO <-- prints bar, still (not expected. Should be nothing) :lua vim.uv.os_setenv("FOO", "buzz") :echo $FOO <-- prints bar, still (not expected. Should be "buzz") Solution: - Remove the `envmap` cache. - Callers to `os_getenv` must free the result. - Update all call-sites. - Introduce `os_getenv_noalloc`. - Extend `os_env_exists()` the `nonempty` parameter.
This commit is contained in:
		@@ -1143,7 +1143,7 @@ static int diff_file(diffio_T *dio)
 | 
				
			|||||||
  char *const cmd = xmalloc(len);
 | 
					  char *const cmd = xmalloc(len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // We don't want $DIFF_OPTIONS to get in the way.
 | 
					  // We don't want $DIFF_OPTIONS to get in the way.
 | 
				
			||||||
  if (os_getenv("DIFF_OPTIONS")) {
 | 
					  if (os_env_exists("DIFF_OPTIONS", true)) {
 | 
				
			||||||
    os_unsetenv("DIFF_OPTIONS");
 | 
					    os_unsetenv("DIFF_OPTIONS");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1556,7 +1556,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
 | 
				
			|||||||
  const char *p = tv_get_string(&argvars[0]);
 | 
					  const char *p = tv_get_string(&argvars[0]);
 | 
				
			||||||
  if (*p == '$') {  // Environment variable.
 | 
					  if (*p == '$') {  // Environment variable.
 | 
				
			||||||
    // First try "normal" environment variables (fast).
 | 
					    // First try "normal" environment variables (fast).
 | 
				
			||||||
    if (os_env_exists(p + 1)) {
 | 
					    if (os_env_exists(p + 1, false)) {
 | 
				
			||||||
      n = true;
 | 
					      n = true;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      // Try expanding things like $VIM and ${HOME}.
 | 
					      // Try expanding things like $VIM and ${HOME}.
 | 
				
			||||||
@@ -3881,9 +3881,9 @@ dict_T *create_environment(const dictitem_T *job_env, const bool clear_env, cons
 | 
				
			|||||||
      size_t len = strlen(required_env_vars[i]);
 | 
					      size_t len = strlen(required_env_vars[i]);
 | 
				
			||||||
      dictitem_T *dv = tv_dict_find(env, required_env_vars[i], (ptrdiff_t)len);
 | 
					      dictitem_T *dv = tv_dict_find(env, required_env_vars[i], (ptrdiff_t)len);
 | 
				
			||||||
      if (!dv) {
 | 
					      if (!dv) {
 | 
				
			||||||
        const char *env_var = os_getenv(required_env_vars[i]);
 | 
					        char *env_var = os_getenv(required_env_vars[i]);
 | 
				
			||||||
        if (env_var) {
 | 
					        if (env_var) {
 | 
				
			||||||
          tv_dict_add_str(env, required_env_vars[i], len, env_var);
 | 
					          tv_dict_add_allocated_str(env, required_env_vars[i], len, env_var);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7810,8 +7810,8 @@ static void ex_checkhealth(exarg_T *eap)
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char *vimruntime_env = os_getenv("VIMRUNTIME");
 | 
					  char *vimruntime_env = os_getenv_noalloc("VIMRUNTIME");
 | 
				
			||||||
  if (vimruntime_env == NULL) {
 | 
					  if (!vimruntime_env) {
 | 
				
			||||||
    emsg(_("E5009: $VIMRUNTIME is empty or unset"));
 | 
					    emsg(_("E5009: $VIMRUNTIME is empty or unset"));
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    bool rtp_ok = NULL != strstr(p_rtp, vimruntime_env);
 | 
					    bool rtp_ok = NULL != strstr(p_rtp, vimruntime_env);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3278,7 +3278,7 @@ static void vim_mktempdir(void)
 | 
				
			|||||||
    expand_env((char *)temp_dirs[i], tmp, TEMP_FILE_PATH_MAXLEN - 64);
 | 
					    expand_env((char *)temp_dirs[i], tmp, TEMP_FILE_PATH_MAXLEN - 64);
 | 
				
			||||||
    if (!os_isdir(tmp)) {
 | 
					    if (!os_isdir(tmp)) {
 | 
				
			||||||
      if (strequal("$TMPDIR", temp_dirs[i])) {
 | 
					      if (strequal("$TMPDIR", temp_dirs[i])) {
 | 
				
			||||||
        if (!os_getenv("TMPDIR")) {
 | 
					        if (!os_env_exists("TMPDIR", true)) {
 | 
				
			||||||
          DLOG("$TMPDIR is unset");
 | 
					          DLOG("$TMPDIR is unset");
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          WLOG("$TMPDIR tempdir not a directory (or does not exist): \"%s\"", tmp);
 | 
					          WLOG("$TMPDIR tempdir not a directory (or does not exist): \"%s\"", tmp);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -336,7 +336,7 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, const char *context,
 | 
				
			|||||||
  // TODO(justinmk): expose this as v:name ?
 | 
					  // TODO(justinmk): expose this as v:name ?
 | 
				
			||||||
  if (regen) {
 | 
					  if (regen) {
 | 
				
			||||||
    // Parent servername ($NVIM).
 | 
					    // Parent servername ($NVIM).
 | 
				
			||||||
    const char *parent = path_tail(os_getenv(ENV_NVIM));
 | 
					    const char *parent = path_tail(os_getenv_noalloc(ENV_NVIM));
 | 
				
			||||||
    // Servername. Empty until starting=false.
 | 
					    // Servername. Empty until starting=false.
 | 
				
			||||||
    const char *serv = path_tail(get_vim_var_str(VV_SEND_SERVER));
 | 
					    const char *serv = path_tail(get_vim_var_str(VV_SEND_SERVER));
 | 
				
			||||||
    if (parent[0] != NUL) {
 | 
					    if (parent[0] != NUL) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -831,8 +831,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
 | 
				
			|||||||
void nlua_init(char **argv, int argc, int lua_arg0)
 | 
					void nlua_init(char **argv, int argc, int lua_arg0)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef NLUA_TRACK_REFS
 | 
					#ifdef NLUA_TRACK_REFS
 | 
				
			||||||
  const char *env = os_getenv("NVIM_LUA_NOTRACK");
 | 
					  if (os_env_exists("NVIM_LUA_NOTRACK", true)) {
 | 
				
			||||||
  if (!env || !*env) {
 | 
					 | 
				
			||||||
    nlua_track_refs = true;
 | 
					    nlua_track_refs = true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -1283,7 +1282,7 @@ static int nlua_empty_dict_tostring(lua_State *lstate)
 | 
				
			|||||||
/// @param  lstate  Lua interpreter state.
 | 
					/// @param  lstate  Lua interpreter state.
 | 
				
			||||||
static int nlua_getenv(lua_State *lstate)
 | 
					static int nlua_getenv(lua_State *lstate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  lua_pushstring(lstate, os_getenv(luaL_checkstring(lstate, 1)));
 | 
					  lua_pushstring(lstate, os_getenv_noalloc(luaL_checkstring(lstate, 1)));
 | 
				
			||||||
  return 1;
 | 
					  return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -938,12 +938,11 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr,
 | 
				
			|||||||
    if (!chan) {
 | 
					    if (!chan) {
 | 
				
			||||||
      fprintf(stderr, "Remote ui failed to start: %s\n", connect_error);
 | 
					      fprintf(stderr, "Remote ui failed to start: %s\n", connect_error);
 | 
				
			||||||
      os_exit(1);
 | 
					      os_exit(1);
 | 
				
			||||||
    } else if (strequal(server_addr, os_getenv("NVIM"))) {
 | 
					    } else if (strequal(server_addr, os_getenv_noalloc("NVIM"))) {
 | 
				
			||||||
      fprintf(stderr, "%s", "Cannot attach UI of :terminal child to its parent. ");
 | 
					      fprintf(stderr, "%s", "Cannot attach UI of :terminal child to its parent. ");
 | 
				
			||||||
      fprintf(stderr, "%s\n", "(Unset $NVIM to skip this check)");
 | 
					      fprintf(stderr, "%s\n", "(Unset $NVIM to skip this check)");
 | 
				
			||||||
      os_exit(1);
 | 
					      os_exit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    ui_client_channel_id = chan;
 | 
					    ui_client_channel_id = chan;
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -2118,7 +2117,7 @@ static void source_startup_scripts(const mparm_T *const parmp)
 | 
				
			|||||||
static int execute_env(char *env)
 | 
					static int execute_env(char *env)
 | 
				
			||||||
  FUNC_ATTR_NONNULL_ALL
 | 
					  FUNC_ATTR_NONNULL_ALL
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  const char *initstr = os_getenv(env);
 | 
					  char *initstr = os_getenv(env);
 | 
				
			||||||
  if (initstr == NULL) {
 | 
					  if (initstr == NULL) {
 | 
				
			||||||
    return FAIL;
 | 
					    return FAIL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -2132,6 +2131,8 @@ static int execute_env(char *env)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  estack_pop();
 | 
					  estack_pop();
 | 
				
			||||||
  current_sctx = save_current_sctx;
 | 
					  current_sctx = save_current_sctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  xfree(initstr);
 | 
				
			||||||
  return OK;
 | 
					  return OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2412,14 +2412,15 @@ char *enc_locale(void)
 | 
				
			|||||||
  char buf[50];
 | 
					  char buf[50];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char *s;
 | 
					  const char *s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_NL_LANGINFO_CODESET
 | 
					#ifdef HAVE_NL_LANGINFO_CODESET
 | 
				
			||||||
  if (!(s = nl_langinfo(CODESET)) || *s == NUL)
 | 
					  if (!(s = nl_langinfo(CODESET)) || *s == NUL)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    if (!(s = setlocale(LC_CTYPE, NULL)) || *s == NUL) {
 | 
					    if (!(s = setlocale(LC_CTYPE, NULL)) || *s == NUL) {
 | 
				
			||||||
      if ((s = os_getenv("LC_ALL"))) {
 | 
					      if ((s = os_getenv_noalloc("LC_ALL"))) {
 | 
				
			||||||
        if ((s = os_getenv("LC_CTYPE"))) {
 | 
					        if ((s = os_getenv_noalloc("LC_CTYPE"))) {
 | 
				
			||||||
          s = os_getenv("LANG");
 | 
					          s = os_getenv_noalloc("LANG");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -788,7 +788,6 @@ void free_all_mem(void)
 | 
				
			|||||||
  free_all_marks();
 | 
					  free_all_marks();
 | 
				
			||||||
  alist_clear(&global_alist);
 | 
					  alist_clear(&global_alist);
 | 
				
			||||||
  free_homedir();
 | 
					  free_homedir();
 | 
				
			||||||
  free_envmap();
 | 
					 | 
				
			||||||
  free_users();
 | 
					  free_users();
 | 
				
			||||||
  free_search_patterns();
 | 
					  free_search_patterns();
 | 
				
			||||||
  free_old_sub();
 | 
					  free_old_sub();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,28 +41,24 @@ bool server_init(const char *listen_addr)
 | 
				
			|||||||
  ga_init(&watchers, sizeof(SocketWatcher *), 1);
 | 
					  ga_init(&watchers, sizeof(SocketWatcher *), 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // $NVIM_LISTEN_ADDRESS (deprecated)
 | 
					  // $NVIM_LISTEN_ADDRESS (deprecated)
 | 
				
			||||||
  if ((!listen_addr || listen_addr[0] == '\0') && os_env_exists(ENV_LISTEN)) {
 | 
					  if (!listen_addr || listen_addr[0] == '\0') {
 | 
				
			||||||
 | 
					    if (os_env_exists(ENV_LISTEN, true)) {
 | 
				
			||||||
      user_arg = kFalse;  // User-provided env var.
 | 
					      user_arg = kFalse;  // User-provided env var.
 | 
				
			||||||
      listen_addr = os_getenv(ENV_LISTEN);
 | 
					      listen_addr = os_getenv(ENV_LISTEN);
 | 
				
			||||||
  }
 | 
					    } else {
 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!listen_addr || listen_addr[0] == '\0') {
 | 
					 | 
				
			||||||
      user_arg = kNone;  // Autogenerated server address.
 | 
					      user_arg = kNone;  // Autogenerated server address.
 | 
				
			||||||
      listen_addr = server_address_new(NULL);
 | 
					      listen_addr = server_address_new(NULL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    must_free = true;
 | 
					    must_free = true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int rv = server_start(listen_addr);
 | 
					  int rv = server_start(listen_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO(justinmk): this is for log_spec. Can remove this after nvim_log #7062 is merged.
 | 
					  // TODO(justinmk): this is for log_spec. Can remove this after nvim_log #7062 is merged.
 | 
				
			||||||
  if (os_env_exists("__NVIM_TEST_LOG")) {
 | 
					  if (os_env_exists("__NVIM_TEST_LOG", false)) {
 | 
				
			||||||
    ELOG("test log message");
 | 
					    ELOG("test log message");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (must_free) {
 | 
					 | 
				
			||||||
    xfree((char *)listen_addr);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (rv == 0 || user_arg == kNone) {
 | 
					  if (rv == 0 || user_arg == kNone) {
 | 
				
			||||||
    // The autogenerated servername can fail if the user has a broken $XDG_RUNTIME_DIR. #30282
 | 
					    // The autogenerated servername can fail if the user has a broken $XDG_RUNTIME_DIR. #30282
 | 
				
			||||||
    // But that is not fatal (startup will continue, logged in $NVIM_LOGFILE, empty v:servername).
 | 
					    // But that is not fatal (startup will continue, logged in $NVIM_LOGFILE, empty v:servername).
 | 
				
			||||||
@@ -78,12 +74,16 @@ bool server_init(const char *listen_addr)
 | 
				
			|||||||
  ok = false;
 | 
					  ok = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
end:
 | 
					end:
 | 
				
			||||||
  if (os_env_exists(ENV_LISTEN)) {
 | 
					  if (os_env_exists(ENV_LISTEN, false)) {
 | 
				
			||||||
    // Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. It is "input only", it must not be
 | 
					    // Unset $NVIM_LISTEN_ADDRESS, it's a liability hereafter. It is "input only", it must not be
 | 
				
			||||||
    // leaked to child jobs or :terminal.
 | 
					    // leaked to child jobs or :terminal.
 | 
				
			||||||
    os_unsetenv(ENV_LISTEN);
 | 
					    os_unsetenv(ENV_LISTEN);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (must_free) {
 | 
				
			||||||
 | 
					    xfree((char *)listen_addr);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return ok;
 | 
					  return ok;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -120,12 +120,12 @@ char *server_address_new(const char *name)
 | 
				
			|||||||
  static uint32_t count = 0;
 | 
					  static uint32_t count = 0;
 | 
				
			||||||
  char fmt[ADDRESS_MAX_SIZE];
 | 
					  char fmt[ADDRESS_MAX_SIZE];
 | 
				
			||||||
#ifdef MSWIN
 | 
					#ifdef MSWIN
 | 
				
			||||||
  (void)get_appname(true);
 | 
					  (void)get_appname(true);  // Writes appname to NameBuf.
 | 
				
			||||||
  int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32,
 | 
					  int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32,
 | 
				
			||||||
                   name ? name : NameBuff, os_get_pid(), count++);
 | 
					                   name ? name : NameBuff, os_get_pid(), count++);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir);
 | 
					  char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir);
 | 
				
			||||||
  (void)get_appname(true);
 | 
					  (void)get_appname(true);  // Writes appname to NameBuf.
 | 
				
			||||||
  int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32,
 | 
					  int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32,
 | 
				
			||||||
                   dir, name ? name : NameBuff, os_get_pid(), count++);
 | 
					                   dir, name ? name : NameBuff, os_get_pid(), count++);
 | 
				
			||||||
  xfree(dir);
 | 
					  xfree(dir);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -190,7 +190,7 @@ static void set_init_default_shell(void)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  // Find default value for 'shell' option.
 | 
					  // Find default value for 'shell' option.
 | 
				
			||||||
  // Don't use it if it is empty.
 | 
					  // Don't use it if it is empty.
 | 
				
			||||||
  const char *shell = os_getenv("SHELL");
 | 
					  char *shell = os_getenv("SHELL");
 | 
				
			||||||
  if (shell != NULL) {
 | 
					  if (shell != NULL) {
 | 
				
			||||||
    if (vim_strchr(shell, ' ') != NULL) {
 | 
					    if (vim_strchr(shell, ' ') != NULL) {
 | 
				
			||||||
      const size_t len = strlen(shell) + 3;  // two quotes and a trailing NUL
 | 
					      const size_t len = strlen(shell) + 3;  // two quotes and a trailing NUL
 | 
				
			||||||
@@ -198,8 +198,9 @@ static void set_init_default_shell(void)
 | 
				
			|||||||
      snprintf(cmd, len, "\"%s\"", shell);
 | 
					      snprintf(cmd, len, "\"%s\"", shell);
 | 
				
			||||||
      set_string_default(kOptShell, cmd, true);
 | 
					      set_string_default(kOptShell, cmd, true);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      set_string_default(kOptShell, (char *)shell, false);
 | 
					      set_string_default(kOptShell, shell, false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    xfree(shell);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -413,7 +414,7 @@ void set_init_1(bool clean_arg)
 | 
				
			|||||||
  // abilities (bidi namely).
 | 
					  // abilities (bidi namely).
 | 
				
			||||||
  // NOTE: mlterm's author is being asked to 'set' a variable
 | 
					  // NOTE: mlterm's author is being asked to 'set' a variable
 | 
				
			||||||
  //       instead of an environment variable due to inheritance.
 | 
					  //       instead of an environment variable due to inheritance.
 | 
				
			||||||
  if (os_env_exists("MLTERM")) {
 | 
					  if (os_env_exists("MLTERM", false)) {
 | 
				
			||||||
    set_option_value_give_err(kOptTermbidi, BOOLEAN_OPTVAL(true), 0);
 | 
					    set_option_value_give_err(kOptTermbidi, BOOLEAN_OPTVAL(true), 0);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,13 +52,11 @@
 | 
				
			|||||||
# include "os/env.c.generated.h"
 | 
					# include "os/env.c.generated.h"
 | 
				
			||||||
#endif
 | 
					#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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Like getenv(), but returns NULL if the variable is empty.
 | 
					/// Like getenv(), but returns NULL if the variable is empty.
 | 
				
			||||||
 | 
					/// Result must be freed by the caller.
 | 
				
			||||||
/// @see os_env_exists
 | 
					/// @see os_env_exists
 | 
				
			||||||
const char *os_getenv(const char *name)
 | 
					/// @see os_getenv_noalloc
 | 
				
			||||||
 | 
					char *os_getenv(const char *name)
 | 
				
			||||||
  FUNC_ATTR_NONNULL_ALL
 | 
					  FUNC_ATTR_NONNULL_ALL
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  char *e = NULL;
 | 
					  char *e = NULL;
 | 
				
			||||||
@@ -66,17 +64,6 @@ const char *os_getenv(const char *name)
 | 
				
			|||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  int r = 0;
 | 
					  int r = 0;
 | 
				
			||||||
  if (map_has(cstr_t, &envmap, name)
 | 
					 | 
				
			||||||
      && !!(e = (char *)pmap_get(cstr_t)(&envmap, name))) {
 | 
					 | 
				
			||||||
    if (e[0] != NUL) {
 | 
					 | 
				
			||||||
      // Found non-empty cached env var.
 | 
					 | 
				
			||||||
      // NOTE: This risks incoherence if an in-process library changes the
 | 
					 | 
				
			||||||
      //       environment without going through our os_setenv() wrapper.  If
 | 
					 | 
				
			||||||
      //       that turns out to be a problem, we can just remove this codepath.
 | 
					 | 
				
			||||||
      goto end;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    pmap_del2(&envmap, name);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
#define INIT_SIZE 64
 | 
					#define INIT_SIZE 64
 | 
				
			||||||
  size_t size = INIT_SIZE;
 | 
					  size_t size = INIT_SIZE;
 | 
				
			||||||
  char buf[INIT_SIZE];
 | 
					  char buf[INIT_SIZE];
 | 
				
			||||||
@@ -96,7 +83,6 @@ const char *os_getenv(const char *name)
 | 
				
			|||||||
    // except when it does not include the NUL-terminator.
 | 
					    // except when it does not include the NUL-terminator.
 | 
				
			||||||
    e = xmemdupz(buf, size);
 | 
					    e = xmemdupz(buf, size);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  pmap_put(cstr_t)(&envmap, xstrdup(name), e);
 | 
					 | 
				
			||||||
end:
 | 
					end:
 | 
				
			||||||
  if (r != 0 && r != UV_ENOENT && r != UV_UNKNOWN) {
 | 
					  if (r != 0 && r != UV_ENOENT && r != UV_UNKNOWN) {
 | 
				
			||||||
    ELOG("uv_os_getenv(%s) failed: %d %s", name, r, uv_err_name(r));
 | 
					    ELOG("uv_os_getenv(%s) failed: %d %s", name, r, uv_err_name(r));
 | 
				
			||||||
@@ -104,9 +90,43 @@ end:
 | 
				
			|||||||
  return e;
 | 
					  return e;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Like getenv(), but returns a pointer to `NameBuff` instead of allocating, or NULL on failure.
 | 
				
			||||||
 | 
					/// Value is truncated if it exceeds sizeof(NameBuff).
 | 
				
			||||||
 | 
					/// @see os_env_exists
 | 
				
			||||||
 | 
					char *os_getenv_noalloc(const char *name)
 | 
				
			||||||
 | 
					  FUNC_ATTR_NONNULL_ALL
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (name[0] == NUL) {
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  size_t size = sizeof(NameBuff);
 | 
				
			||||||
 | 
					  int r = uv_os_getenv(name, NameBuff, &size);
 | 
				
			||||||
 | 
					  if (r == UV_ENOBUFS) {
 | 
				
			||||||
 | 
					    char *e = xmalloc(size);
 | 
				
			||||||
 | 
					    r = uv_os_getenv(name, e, &size);
 | 
				
			||||||
 | 
					    if (r == 0 && size != 0 && e[0] != NUL) {
 | 
				
			||||||
 | 
					      xmemcpyz(NameBuff, e, sizeof(NameBuff) - 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    xfree(e);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (r != 0 || size == 0 || NameBuff[0] == NUL) {
 | 
				
			||||||
 | 
					    if (r != 0 && r != UV_ENOENT && r != UV_UNKNOWN) {
 | 
				
			||||||
 | 
					      ELOG("uv_os_getenv(%s) failed: %d %s", name, r, uv_err_name(r));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return NameBuff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Returns true if environment variable `name` is defined (even if empty).
 | 
					/// Returns true if environment variable `name` is defined (even if empty).
 | 
				
			||||||
/// Returns false if not found (UV_ENOENT) or other failure.
 | 
					/// Returns false if not found (UV_ENOENT) or other failure.
 | 
				
			||||||
bool os_env_exists(const char *name)
 | 
					///
 | 
				
			||||||
 | 
					/// @param name the environment variable in question
 | 
				
			||||||
 | 
					/// @param nonempty Require a non-empty value. Treat empty as "does not exist".
 | 
				
			||||||
 | 
					/// @return whether the variable exists
 | 
				
			||||||
 | 
					bool os_env_exists(const char *name, bool nonempty)
 | 
				
			||||||
  FUNC_ATTR_NONNULL_ALL
 | 
					  FUNC_ATTR_NONNULL_ALL
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  if (name[0] == NUL) {
 | 
					  if (name[0] == NUL) {
 | 
				
			||||||
@@ -114,14 +134,14 @@ bool os_env_exists(const char *name)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  // Use a tiny buffer because we don't care about the value: if uv_os_getenv()
 | 
					  // Use a tiny buffer because we don't care about the value: if uv_os_getenv()
 | 
				
			||||||
  // returns UV_ENOBUFS, the env var was found.
 | 
					  // returns UV_ENOBUFS, the env var was found.
 | 
				
			||||||
  char buf[1];
 | 
					  char buf[2];
 | 
				
			||||||
  size_t size = sizeof(buf);
 | 
					  size_t size = sizeof(buf);
 | 
				
			||||||
  int r = uv_os_getenv(name, buf, &size);
 | 
					  int r = uv_os_getenv(name, buf, &size);
 | 
				
			||||||
  assert(r != UV_EINVAL);
 | 
					  assert(r != UV_EINVAL);
 | 
				
			||||||
  if (r != 0 && r != UV_ENOENT && r != UV_ENOBUFS) {
 | 
					  if (r != 0 && r != UV_ENOENT && r != UV_ENOBUFS) {
 | 
				
			||||||
    ELOG("uv_os_getenv(%s) failed: %d %s", name, r, uv_err_name(r));
 | 
					    ELOG("uv_os_getenv(%s) failed: %d %s", name, r, uv_err_name(r));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return (r == 0 || r == UV_ENOBUFS);
 | 
					  return ((r == 0 && (!nonempty || size > 0)) || r == UV_ENOBUFS);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Sets an environment variable.
 | 
					/// Sets an environment variable.
 | 
				
			||||||
@@ -137,7 +157,7 @@ int os_setenv(const char *name, const char *value, int overwrite)
 | 
				
			|||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#ifdef MSWIN
 | 
					#ifdef MSWIN
 | 
				
			||||||
  if (!overwrite && os_getenv(name) != NULL) {
 | 
					  if (!overwrite && !os_env_exists(name, true)) {
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (value[0] == NUL) {
 | 
					  if (value[0] == NUL) {
 | 
				
			||||||
@@ -145,7 +165,7 @@ int os_setenv(const char *name, const char *value, int overwrite)
 | 
				
			|||||||
    return os_unsetenv(name);
 | 
					    return os_unsetenv(name);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  if (!overwrite && os_env_exists(name)) {
 | 
					  if (!overwrite && os_env_exists(name, false)) {
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -160,9 +180,6 @@ int os_setenv(const char *name, const char *value, int overwrite)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
  r = uv_os_setenv(name, value);
 | 
					  r = uv_os_setenv(name, value);
 | 
				
			||||||
  assert(r != UV_EINVAL);
 | 
					  assert(r != UV_EINVAL);
 | 
				
			||||||
  // Destroy the old map item. Do this AFTER uv_os_setenv(), because `value`
 | 
					 | 
				
			||||||
  // could be a previous os_getenv() result.
 | 
					 | 
				
			||||||
  pmap_del2(&envmap, name);
 | 
					 | 
				
			||||||
  if (r != 0) {
 | 
					  if (r != 0) {
 | 
				
			||||||
    ELOG("uv_os_setenv(%s) failed: %d %s", name, r, uv_err_name(r));
 | 
					    ELOG("uv_os_setenv(%s) failed: %d %s", name, r, uv_err_name(r));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -176,7 +193,6 @@ int os_unsetenv(const char *name)
 | 
				
			|||||||
  if (name[0] == NUL) {
 | 
					  if (name[0] == NUL) {
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  pmap_del2(&envmap, name);
 | 
					 | 
				
			||||||
  int r = uv_os_unsetenv(name);
 | 
					  int r = uv_os_unsetenv(name);
 | 
				
			||||||
  if (r != 0) {
 | 
					  if (r != 0) {
 | 
				
			||||||
    ELOG("uv_os_unsetenv(%s) failed: %d %s", name, r, uv_err_name(r));
 | 
					    ELOG("uv_os_unsetenv(%s) failed: %d %s", name, r, uv_err_name(r));
 | 
				
			||||||
@@ -428,7 +444,8 @@ void init_homedir(void)
 | 
				
			|||||||
  xfree(homedir);
 | 
					  xfree(homedir);
 | 
				
			||||||
  homedir = NULL;
 | 
					  homedir = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char *var = os_getenv("HOME");
 | 
					  char *var = os_getenv("HOME");
 | 
				
			||||||
 | 
					  char *tofree = var;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef MSWIN
 | 
					#ifdef MSWIN
 | 
				
			||||||
  // Typically, $HOME is not defined on Windows, unless the user has
 | 
					  // Typically, $HOME is not defined on Windows, unless the user has
 | 
				
			||||||
@@ -436,10 +453,10 @@ void init_homedir(void)
 | 
				
			|||||||
  // platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for
 | 
					  // platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for
 | 
				
			||||||
  // each user. Try constructing $HOME from these.
 | 
					  // each user. Try constructing $HOME from these.
 | 
				
			||||||
  if (var == NULL) {
 | 
					  if (var == NULL) {
 | 
				
			||||||
    const char *homedrive = os_getenv("HOMEDRIVE");
 | 
					    char *homedrive = os_getenv("HOMEDRIVE");
 | 
				
			||||||
    const char *homepath = os_getenv("HOMEPATH");
 | 
					    char *homepath = os_getenv("HOMEPATH");
 | 
				
			||||||
    if (homepath == NULL) {
 | 
					    if (homepath == NULL) {
 | 
				
			||||||
      homepath = "\\";
 | 
					      homepath = xstrdup("\\");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (homedrive != NULL
 | 
					    if (homedrive != NULL
 | 
				
			||||||
        && strlen(homedrive) + strlen(homepath) < MAXPATHL) {
 | 
					        && strlen(homedrive) + strlen(homepath) < MAXPATHL) {
 | 
				
			||||||
@@ -448,6 +465,8 @@ void init_homedir(void)
 | 
				
			|||||||
        var = os_buf;
 | 
					        var = os_buf;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    xfree(homepath);
 | 
				
			||||||
 | 
					    xfree(homedrive);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (var == NULL) {
 | 
					  if (var == NULL) {
 | 
				
			||||||
    var = os_uv_homedir();
 | 
					    var = os_uv_homedir();
 | 
				
			||||||
@@ -461,12 +480,14 @@ void init_homedir(void)
 | 
				
			|||||||
    if (p != NULL) {
 | 
					    if (p != NULL) {
 | 
				
			||||||
      vim_snprintf(os_buf, (size_t)(p - var), "%s", var + 1);
 | 
					      vim_snprintf(os_buf, (size_t)(p - var), "%s", var + 1);
 | 
				
			||||||
      var = NULL;
 | 
					      var = NULL;
 | 
				
			||||||
      const char *exp = os_getenv(os_buf);
 | 
					      char *exp = os_getenv(os_buf);
 | 
				
			||||||
      if (exp != NULL && *exp != NUL
 | 
					      if (exp != NULL) {
 | 
				
			||||||
          && strlen(exp) + strlen(p) < MAXPATHL) {
 | 
					        if (*exp != NUL && strlen(exp) + strlen(p) < MAXPATHL) {
 | 
				
			||||||
          vim_snprintf(os_buf, MAXPATHL, "%s%s", exp, p + 1);
 | 
					          vim_snprintf(os_buf, MAXPATHL, "%s%s", exp, p + 1);
 | 
				
			||||||
          var = os_buf;
 | 
					          var = os_buf;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        xfree(exp);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -498,6 +519,7 @@ void init_homedir(void)
 | 
				
			|||||||
  if (var != NULL) {
 | 
					  if (var != NULL) {
 | 
				
			||||||
    homedir = xstrdup(var);
 | 
					    homedir = xstrdup(var);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  xfree(tofree);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char homedir_buf[MAXPATHL];
 | 
					static char homedir_buf[MAXPATHL];
 | 
				
			||||||
@@ -523,17 +545,6 @@ void free_homedir(void)
 | 
				
			|||||||
  xfree(homedir);
 | 
					  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
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Call expand_env() and store the result in an allocated string.
 | 
					/// Call expand_env() and store the result in an allocated string.
 | 
				
			||||||
@@ -917,9 +928,9 @@ char *vim_getenv(const char *name)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char *kos_env_path = os_getenv(name);
 | 
					  char *kos_env_path = os_getenv(name);
 | 
				
			||||||
  if (kos_env_path != NULL) {
 | 
					  if (kos_env_path != NULL) {
 | 
				
			||||||
    return xstrdup(kos_env_path);
 | 
					    return kos_env_path;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool vimruntime = (strcmp(name, "VIMRUNTIME") == 0);
 | 
					  bool vimruntime = (strcmp(name, "VIMRUNTIME") == 0);
 | 
				
			||||||
@@ -932,11 +943,13 @@ char *vim_getenv(const char *name)
 | 
				
			|||||||
  char *vim_path = NULL;
 | 
					  char *vim_path = NULL;
 | 
				
			||||||
  if (vimruntime
 | 
					  if (vimruntime
 | 
				
			||||||
      && *default_vimruntime_dir == NUL) {
 | 
					      && *default_vimruntime_dir == NUL) {
 | 
				
			||||||
    kos_env_path = os_getenv("VIM");
 | 
					    kos_env_path = os_getenv("VIM");    // kos_env_path was NULL.
 | 
				
			||||||
    if (kos_env_path != NULL) {
 | 
					    if (kos_env_path != NULL) {
 | 
				
			||||||
      vim_path = vim_version_dir(kos_env_path);
 | 
					      vim_path = vim_version_dir(kos_env_path);
 | 
				
			||||||
      if (vim_path == NULL) {
 | 
					      if (vim_path == NULL) {
 | 
				
			||||||
        vim_path = xstrdup(kos_env_path);
 | 
					        vim_path = kos_env_path;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        xfree(kos_env_path);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1059,13 +1072,13 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si
 | 
				
			|||||||
    dirlen = strlen(homedir);
 | 
					    dirlen = strlen(homedir);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char *homedir_env = os_getenv("HOME");
 | 
					  char *homedir_env = os_getenv("HOME");
 | 
				
			||||||
#ifdef MSWIN
 | 
					#ifdef MSWIN
 | 
				
			||||||
  if (homedir_env == NULL) {
 | 
					  if (homedir_env == NULL) {
 | 
				
			||||||
    homedir_env = os_getenv("USERPROFILE");
 | 
					    homedir_env = os_getenv("USERPROFILE");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  char *homedir_env_mod = (char *)homedir_env;
 | 
					  char *homedir_env_mod = homedir_env;
 | 
				
			||||||
  bool must_free = false;
 | 
					  bool must_free = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (homedir_env_mod != NULL && *homedir_env_mod == '~') {
 | 
					  if (homedir_env_mod != NULL && *homedir_env_mod == '~') {
 | 
				
			||||||
@@ -1142,6 +1155,8 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  *dst_p = NUL;
 | 
					  *dst_p = NUL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  xfree(homedir_env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (must_free) {
 | 
					  if (must_free) {
 | 
				
			||||||
    xfree(homedir_env_mod);
 | 
					    xfree(homedir_env_mod);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1199,9 +1214,10 @@ bool os_setenv_append_path(const char *fname)
 | 
				
			|||||||
  size_t dirlen = (size_t)(tail - fname);
 | 
					  size_t dirlen = (size_t)(tail - fname);
 | 
				
			||||||
  assert(tail >= fname && dirlen + 1 < sizeof(os_buf));
 | 
					  assert(tail >= fname && dirlen + 1 < sizeof(os_buf));
 | 
				
			||||||
  xmemcpyz(os_buf, fname, dirlen);
 | 
					  xmemcpyz(os_buf, fname, dirlen);
 | 
				
			||||||
  const char *path = os_getenv("PATH");
 | 
					  char *path = os_getenv("PATH");
 | 
				
			||||||
  const size_t pathlen = path ? strlen(path) : 0;
 | 
					  const size_t pathlen = path ? strlen(path) : 0;
 | 
				
			||||||
  const size_t newlen = pathlen + dirlen + 2;
 | 
					  const size_t newlen = pathlen + dirlen + 2;
 | 
				
			||||||
 | 
					  bool retval = false;
 | 
				
			||||||
  if (newlen < MAX_ENVPATHLEN) {
 | 
					  if (newlen < MAX_ENVPATHLEN) {
 | 
				
			||||||
    char *temp = xmalloc(newlen);
 | 
					    char *temp = xmalloc(newlen);
 | 
				
			||||||
    if (pathlen == 0) {
 | 
					    if (pathlen == 0) {
 | 
				
			||||||
@@ -1215,9 +1231,10 @@ bool os_setenv_append_path(const char *fname)
 | 
				
			|||||||
    xstrlcat(temp, os_buf, newlen);
 | 
					    xstrlcat(temp, os_buf, newlen);
 | 
				
			||||||
    os_setenv("PATH", temp, 1);
 | 
					    os_setenv("PATH", temp, 1);
 | 
				
			||||||
    xfree(temp);
 | 
					    xfree(temp);
 | 
				
			||||||
    return true;
 | 
					    retval = true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return false;
 | 
					  xfree(path);
 | 
				
			||||||
 | 
					  return retval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Returns true if `sh` looks like it resolves to "cmd.exe".
 | 
					/// Returns true if `sh` looks like it resolves to "cmd.exe".
 | 
				
			||||||
@@ -1228,7 +1245,7 @@ bool os_shell_is_cmdexe(const char *sh)
 | 
				
			|||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (striequal(sh, "$COMSPEC")) {
 | 
					  if (striequal(sh, "$COMSPEC")) {
 | 
				
			||||||
    const char *comspec = os_getenv("COMSPEC");
 | 
					    char *comspec = os_getenv_noalloc("COMSPEC");
 | 
				
			||||||
    return striequal("cmd.exe", path_tail(comspec));
 | 
					    return striequal("cmd.exe", path_tail(comspec));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (striequal(sh, "cmd.exe") || striequal(sh, "cmd")) {
 | 
					  if (striequal(sh, "cmd.exe") || striequal(sh, "cmd")) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -303,7 +303,7 @@ static bool is_executable_ext(const char *name, char **abspath)
 | 
				
			|||||||
  size_t nameext_len = nameext ? strlen(nameext) : 0;
 | 
					  size_t nameext_len = nameext ? strlen(nameext) : 0;
 | 
				
			||||||
  xstrlcpy(os_buf, name, sizeof(os_buf));
 | 
					  xstrlcpy(os_buf, name, sizeof(os_buf));
 | 
				
			||||||
  char *buf_end = xstrchrnul(os_buf, NUL);
 | 
					  char *buf_end = xstrchrnul(os_buf, NUL);
 | 
				
			||||||
  const char *pathext = os_getenv("PATHEXT");
 | 
					  const char *pathext = os_getenv_noalloc("PATHEXT");
 | 
				
			||||||
  if (!pathext) {
 | 
					  if (!pathext) {
 | 
				
			||||||
    pathext = ".com;.exe;.bat;.cmd";
 | 
					    pathext = ".com;.exe;.bat;.cmd";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -350,14 +350,14 @@ static bool is_executable_ext(const char *name, char **abspath)
 | 
				
			|||||||
static bool is_executable_in_path(const char *name, char **abspath)
 | 
					static bool is_executable_in_path(const char *name, char **abspath)
 | 
				
			||||||
  FUNC_ATTR_NONNULL_ARG(1)
 | 
					  FUNC_ATTR_NONNULL_ARG(1)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  const char *path_env = os_getenv("PATH");
 | 
					  char *path_env = os_getenv("PATH");
 | 
				
			||||||
  if (path_env == NULL) {
 | 
					  if (path_env == NULL) {
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef MSWIN
 | 
					#ifdef MSWIN
 | 
				
			||||||
  char *path = NULL;
 | 
					  char *path = NULL;
 | 
				
			||||||
  if (!os_env_exists("NoDefaultCurrentDirectoryInExePath")) {
 | 
					  if (!os_env_exists("NoDefaultCurrentDirectoryInExePath", false)) {
 | 
				
			||||||
    // Prepend ".;" to $PATH.
 | 
					    // Prepend ".;" to $PATH.
 | 
				
			||||||
    size_t pathlen = strlen(path_env);
 | 
					    size_t pathlen = strlen(path_env);
 | 
				
			||||||
    path = xmallocz(pathlen + 2);
 | 
					    path = xmallocz(pathlen + 2);
 | 
				
			||||||
@@ -404,6 +404,7 @@ static bool is_executable_in_path(const char *name, char **abspath)
 | 
				
			|||||||
end:
 | 
					end:
 | 
				
			||||||
  xfree(buf);
 | 
					  xfree(buf);
 | 
				
			||||||
  xfree(path);
 | 
					  xfree(path);
 | 
				
			||||||
 | 
					  xfree(path_env);
 | 
				
			||||||
  return rv;
 | 
					  return rv;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,6 +70,7 @@ char *get_mess_lang(void)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Get the language used for messages from the environment.
 | 
					/// Get the language used for messages from the environment.
 | 
				
			||||||
 | 
					/// The function may be using NameBuff.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// This uses LC_MESSAGES when available, which it is for most systems we build for
 | 
					/// This uses LC_MESSAGES when available, which it is for most systems we build for
 | 
				
			||||||
/// except for windows. Then fallback to get the value from the environment
 | 
					/// except for windows. Then fallback to get the value from the environment
 | 
				
			||||||
@@ -79,17 +80,17 @@ static char *get_mess_env(void)
 | 
				
			|||||||
#ifdef LC_MESSAGES
 | 
					#ifdef LC_MESSAGES
 | 
				
			||||||
  return get_locale_val(LC_MESSAGES);
 | 
					  return get_locale_val(LC_MESSAGES);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  char *p = (char *)os_getenv("LC_ALL");
 | 
					  char *p = os_getenv_noalloc("LC_ALL");
 | 
				
			||||||
  if (p != NULL) {
 | 
					  if (p != NULL) {
 | 
				
			||||||
    return p;
 | 
					    return p;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  p = (char *)os_getenv("LC_MESSAGES");
 | 
					  p = os_getenv_noalloc("LC_MESSAGES");
 | 
				
			||||||
  if (p != NULL) {
 | 
					  if (p != NULL) {
 | 
				
			||||||
    return p;
 | 
					    return p;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  p = (char *)os_getenv("LANG");
 | 
					  p = os_getenv_noalloc("LANG");
 | 
				
			||||||
  if (p != NULL && ascii_isdigit(*p)) {
 | 
					  if (p != NULL && ascii_isdigit(*p)) {
 | 
				
			||||||
    p = NULL;  // ignore something like "1043"
 | 
					    p = NULL;  // ignore something like "1043"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -340,7 +341,7 @@ char *get_locales(expand_T *xp, int idx)
 | 
				
			|||||||
void lang_init(void)
 | 
					void lang_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef __APPLE__
 | 
					#ifdef __APPLE__
 | 
				
			||||||
  if (os_getenv("LANG") == NULL) {
 | 
					  if (!os_env_exists("LANG", true)) {
 | 
				
			||||||
    char buf[50] = { 0 };
 | 
					    char buf[50] = { 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // $LANG is not set, either because it was unset or Nvim was started
 | 
					    // $LANG is not set, either because it was unset or Nvim was started
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,7 +82,7 @@ void os_icon_init(void)
 | 
				
			|||||||
  hOrigIconSmall = (HICON)SendMessage(hWnd, WM_GETICON, (WPARAM)ICON_SMALL, (LPARAM)0);
 | 
					  hOrigIconSmall = (HICON)SendMessage(hWnd, WM_GETICON, (WPARAM)ICON_SMALL, (LPARAM)0);
 | 
				
			||||||
  hOrigIcon = (HICON)SendMessage(hWnd, WM_GETICON, (WPARAM)ICON_BIG, (LPARAM)0);
 | 
					  hOrigIcon = (HICON)SendMessage(hWnd, WM_GETICON, (WPARAM)ICON_BIG, (LPARAM)0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char *vimruntime = os_getenv("VIMRUNTIME");
 | 
					  char *vimruntime = os_getenv("VIMRUNTIME");
 | 
				
			||||||
  if (vimruntime != NULL) {
 | 
					  if (vimruntime != NULL) {
 | 
				
			||||||
    snprintf(NameBuff, MAXPATHL, "%s/neovim.ico", vimruntime);
 | 
					    snprintf(NameBuff, MAXPATHL, "%s/neovim.ico", vimruntime);
 | 
				
			||||||
    if (!os_path_exists(NameBuff)) {
 | 
					    if (!os_path_exists(NameBuff)) {
 | 
				
			||||||
@@ -92,6 +92,7 @@ void os_icon_init(void)
 | 
				
			|||||||
                                 LR_LOADFROMFILE | LR_LOADMAP3DCOLORS);
 | 
					                                 LR_LOADFROMFILE | LR_LOADMAP3DCOLORS);
 | 
				
			||||||
      os_icon_set(hVimIcon, hVimIcon);
 | 
					      os_icon_set(hVimIcon, hVimIcon);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    xfree(vimruntime);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -117,7 +118,7 @@ void os_title_reset(void)
 | 
				
			|||||||
/// @param out_fd stdout file descriptor
 | 
					/// @param out_fd stdout file descriptor
 | 
				
			||||||
void os_tty_guess_term(const char **term, int out_fd)
 | 
					void os_tty_guess_term(const char **term, int out_fd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  bool conemu_ansi = strequal(os_getenv("ConEmuANSI"), "ON");
 | 
					  bool conemu_ansi = strequal(os_getenv_noalloc("ConEmuANSI"), "ON");
 | 
				
			||||||
  bool vtp = false;
 | 
					  bool vtp = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HANDLE handle = (HANDLE)_get_osfhandle(out_fd);
 | 
					  HANDLE handle = (HANDLE)_get_osfhandle(out_fd);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,19 +70,19 @@ static const char *const xdg_defaults[] = {
 | 
				
			|||||||
/// @return $NVIM_APPNAME value
 | 
					/// @return $NVIM_APPNAME value
 | 
				
			||||||
const char *get_appname(bool namelike)
 | 
					const char *get_appname(bool namelike)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  const char *env_val = os_getenv("NVIM_APPNAME");
 | 
					  const char *env_val = os_getenv_noalloc("NVIM_APPNAME");
 | 
				
			||||||
  if (env_val == NULL || *env_val == NUL) {
 | 
					
 | 
				
			||||||
    env_val = "nvim";
 | 
					  if (!env_val) {
 | 
				
			||||||
 | 
					    xstrlcpy(NameBuff, "nvim", sizeof(NameBuff));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (namelike) {
 | 
					  if (namelike) {
 | 
				
			||||||
    // Appname may be a relative path, replace slashes to make it name-like.
 | 
					    // Appname may be a relative path, replace slashes to make it name-like.
 | 
				
			||||||
    xstrlcpy(NameBuff, env_val, sizeof(NameBuff));
 | 
					 | 
				
			||||||
    memchrsub(NameBuff, '/', '-', sizeof(NameBuff));
 | 
					    memchrsub(NameBuff, '/', '-', sizeof(NameBuff));
 | 
				
			||||||
    memchrsub(NameBuff, '\\', '-', sizeof(NameBuff));
 | 
					    memchrsub(NameBuff, '\\', '-', sizeof(NameBuff));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return env_val;
 | 
					  return NameBuff;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Ensure that APPNAME is valid. Must be a name or relative path.
 | 
					/// Ensure that APPNAME is valid. Must be a name or relative path.
 | 
				
			||||||
@@ -157,21 +157,21 @@ char *stdpaths_get_xdg_var(const XDGVarType idx)
 | 
				
			|||||||
  const char *const env = xdg_env_vars[idx];
 | 
					  const char *const env = xdg_env_vars[idx];
 | 
				
			||||||
  const char *const fallback = xdg_defaults[idx];
 | 
					  const char *const fallback = xdg_defaults[idx];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char *env_val = os_getenv(env);
 | 
					  char *env_val = os_getenv(env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef MSWIN
 | 
					#ifdef MSWIN
 | 
				
			||||||
  if (env_val == NULL && xdg_defaults_env_vars[idx] != NULL) {
 | 
					  if (env_val == NULL && xdg_defaults_env_vars[idx] != NULL) {
 | 
				
			||||||
    env_val = os_getenv(xdg_defaults_env_vars[idx]);
 | 
					    env_val = os_getenv(xdg_defaults_env_vars[idx]);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  if (env_val == NULL && os_env_exists(env)) {
 | 
					  if (env_val == NULL && os_env_exists(env, false)) {
 | 
				
			||||||
    env_val = "";
 | 
					    env_val = xstrdup("");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  char *ret = NULL;
 | 
					  char *ret = NULL;
 | 
				
			||||||
  if (env_val != NULL) {
 | 
					  if (env_val != NULL) {
 | 
				
			||||||
    ret = xstrdup(env_val);
 | 
					    ret = env_val;
 | 
				
			||||||
  } else if (fallback) {
 | 
					  } else if (fallback) {
 | 
				
			||||||
    ret = expand_env_save((char *)fallback);
 | 
					    ret = expand_env_save((char *)fallback);
 | 
				
			||||||
  } else if (idx == kXDGRuntimeDir) {
 | 
					  } else if (idx == kXDGRuntimeDir) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -98,8 +98,8 @@ struct tm *os_localtime_r(const time_t *restrict clock,
 | 
				
			|||||||
  // Call tzset(3) to update the global timezone variables if it has.
 | 
					  // Call tzset(3) to update the global timezone variables if it has.
 | 
				
			||||||
  // POSIX standard doesn't require localtime_r() implementations to do that
 | 
					  // POSIX standard doesn't require localtime_r() implementations to do that
 | 
				
			||||||
  // as it does with localtime(), and we don't want to call tzset() every time.
 | 
					  // as it does with localtime(), and we don't want to call tzset() every time.
 | 
				
			||||||
  const char *tz = os_getenv("TZ");
 | 
					  const char *tz = os_getenv_noalloc("TZ");
 | 
				
			||||||
  if (tz == NULL) {
 | 
					  if (!tz) {
 | 
				
			||||||
    tz = "";
 | 
					    tz = "";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (strncmp(tz_cache, tz, sizeof(tz_cache) - 1) != 0) {
 | 
					  if (strncmp(tz_cache, tz, sizeof(tz_cache) - 1) != 0) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,7 +89,7 @@ int os_get_usernames(garray_T *users)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef HAVE_PWD_FUNCS
 | 
					#ifdef HAVE_PWD_FUNCS
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    const char *user_env = os_getenv("USER");
 | 
					    char *user_env = os_getenv_noalloc("USER");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The $USER environment variable may be a valid remote user name (NIS,
 | 
					    // The $USER environment variable may be a valid remote user name (NIS,
 | 
				
			||||||
    // LDAP) not already listed by getpwent(), as getpwent() only lists
 | 
					    // LDAP) not already listed by getpwent(), as getpwent() only lists
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2392,7 +2392,7 @@ bool path_is_absolute(const char *fname)
 | 
				
			|||||||
void path_guess_exepath(const char *argv0, char *buf, size_t bufsize)
 | 
					void path_guess_exepath(const char *argv0, char *buf, size_t bufsize)
 | 
				
			||||||
  FUNC_ATTR_NONNULL_ALL
 | 
					  FUNC_ATTR_NONNULL_ALL
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  const char *path = os_getenv("PATH");
 | 
					  char *path = os_getenv("PATH");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (path == NULL || path_is_absolute(argv0)) {
 | 
					  if (path == NULL || path_is_absolute(argv0)) {
 | 
				
			||||||
    xstrlcpy(buf, argv0, bufsize);
 | 
					    xstrlcpy(buf, argv0, bufsize);
 | 
				
			||||||
@@ -2427,4 +2427,5 @@ void path_guess_exepath(const char *argv0, char *buf, size_t bufsize)
 | 
				
			|||||||
    // Not found in $PATH, fall back to argv0.
 | 
					    // Not found in $PATH, fall back to argv0.
 | 
				
			||||||
    xstrlcpy(buf, argv0, bufsize);
 | 
					    xstrlcpy(buf, argv0, bufsize);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  xfree(path);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1746,8 +1746,7 @@ char *runtimepath_default(bool clean_arg)
 | 
				
			|||||||
  size_t config_len = 0;
 | 
					  size_t config_len = 0;
 | 
				
			||||||
  size_t vimruntime_len = 0;
 | 
					  size_t vimruntime_len = 0;
 | 
				
			||||||
  size_t libdir_len = 0;
 | 
					  size_t libdir_len = 0;
 | 
				
			||||||
  const char *appname = get_appname(false);
 | 
					  size_t appname_len = strlen(get_appname(false));
 | 
				
			||||||
  size_t appname_len = strlen(appname);
 | 
					 | 
				
			||||||
  if (data_home != NULL) {
 | 
					  if (data_home != NULL) {
 | 
				
			||||||
    data_len = strlen(data_home);
 | 
					    data_len = strlen(data_home);
 | 
				
			||||||
    size_t nvim_data_size = appname_len;
 | 
					    size_t nvim_data_size = appname_len;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -139,7 +139,8 @@ void tinput_init(TermInput *input, Loop *loop)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  input->in_fd = STDIN_FILENO;
 | 
					  input->in_fd = STDIN_FILENO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char *term = os_getenv("TERM");
 | 
					  const char *term = os_getenv_noalloc("TERM");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!term) {
 | 
					  if (!term) {
 | 
				
			||||||
    term = "";  // termkey_new_abstract assumes non-null (#2745)
 | 
					    term = "";  // termkey_new_abstract assumes non-null (#2745)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,7 @@ bool terminfo_is_bsd_console(const char *term)
 | 
				
			|||||||
# if defined(__FreeBSD__)
 | 
					# if defined(__FreeBSD__)
 | 
				
			||||||
  // FreeBSD console sets TERM=xterm, but it does not support xterm features
 | 
					  // FreeBSD console sets TERM=xterm, but it does not support xterm features
 | 
				
			||||||
  // like cursor-shaping. Assume that TERM=xterm is degraded. #8644
 | 
					  // like cursor-shaping. Assume that TERM=xterm is degraded. #8644
 | 
				
			||||||
  return strequal(term, "xterm") && !!os_getenv("XTERM_VERSION");
 | 
					  return strequal(term, "xterm") && os_env_exists("XTERM_VERSION", true);
 | 
				
			||||||
# endif
 | 
					# endif
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  return false;
 | 
					  return false;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -379,7 +379,7 @@ static void terminfo_start(TUIData *tui)
 | 
				
			|||||||
  tui->out_isatty = os_isatty(tui->out_fd);
 | 
					  tui->out_isatty = os_isatty(tui->out_fd);
 | 
				
			||||||
  tui->input.tui_data = tui;
 | 
					  tui->input.tui_data = tui;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char *term = os_getenv("TERM");
 | 
					  char *term = os_getenv("TERM");
 | 
				
			||||||
#ifdef MSWIN
 | 
					#ifdef MSWIN
 | 
				
			||||||
  os_tty_guess_term(&term, tui->out_fd);
 | 
					  os_tty_guess_term(&term, tui->out_fd);
 | 
				
			||||||
  os_setenv("TERM", term, 1);
 | 
					  os_setenv("TERM", term, 1);
 | 
				
			||||||
@@ -401,23 +401,25 @@ static void terminfo_start(TUIData *tui)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // None of the following work over SSH; see :help TERM .
 | 
					  // None of the following work over SSH; see :help TERM .
 | 
				
			||||||
  const char *colorterm = os_getenv("COLORTERM");
 | 
					  char *colorterm = os_getenv("COLORTERM");
 | 
				
			||||||
  const char *termprg = os_getenv("TERM_PROGRAM");
 | 
					  char *termprg = os_getenv("TERM_PROGRAM");
 | 
				
			||||||
  const char *vte_version_env = os_getenv("VTE_VERSION");
 | 
					  char *vte_version_env = os_getenv("VTE_VERSION");
 | 
				
			||||||
 | 
					  char *konsolev_env = os_getenv("KONSOLE_VERSION");
 | 
				
			||||||
 | 
					  char *term_program_version_env = os_getenv("TERM_PROGRAM_VERSION");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int vtev = vte_version_env ? (int)strtol(vte_version_env, NULL, 10) : 0;
 | 
					  int vtev = vte_version_env ? (int)strtol(vte_version_env, NULL, 10) : 0;
 | 
				
			||||||
  bool iterm_env = termprg && strstr(termprg, "iTerm.app");
 | 
					  bool iterm_env = termprg && strstr(termprg, "iTerm.app");
 | 
				
			||||||
  bool nsterm = (termprg && strstr(termprg, "Apple_Terminal"))
 | 
					  bool nsterm = (termprg && strstr(termprg, "Apple_Terminal"))
 | 
				
			||||||
                || terminfo_is_term_family(term, "nsterm");
 | 
					                || terminfo_is_term_family(term, "nsterm");
 | 
				
			||||||
  bool konsole = terminfo_is_term_family(term, "konsole")
 | 
					  bool konsole = terminfo_is_term_family(term, "konsole")
 | 
				
			||||||
                 || os_getenv("KONSOLE_PROFILE_NAME")
 | 
					                 || os_env_exists("KONSOLE_PROFILE_NAME", true)
 | 
				
			||||||
                 || os_getenv("KONSOLE_DBUS_SESSION");
 | 
					                 || os_env_exists("KONSOLE_DBUS_SESSION", true);
 | 
				
			||||||
  const char *konsolev_env = os_getenv("KONSOLE_VERSION");
 | 
					 | 
				
			||||||
  int konsolev = konsolev_env ? (int)strtol(konsolev_env, NULL, 10)
 | 
					  int konsolev = konsolev_env ? (int)strtol(konsolev_env, NULL, 10)
 | 
				
			||||||
                              : (konsole ? 1 : 0);
 | 
					                              : (konsole ? 1 : 0);
 | 
				
			||||||
  bool wezterm = strequal(termprg, "WezTerm");
 | 
					  bool wezterm = strequal(termprg, "WezTerm");
 | 
				
			||||||
  const char *weztermv = wezterm ? os_getenv("TERM_PROGRAM_VERSION") : NULL;
 | 
					  const char *weztermv = wezterm ? term_program_version_env : NULL;
 | 
				
			||||||
  bool screen = terminfo_is_term_family(term, "screen");
 | 
					  bool screen = terminfo_is_term_family(term, "screen");
 | 
				
			||||||
  bool tmux = terminfo_is_term_family(term, "tmux") || !!os_getenv("TMUX");
 | 
					  bool tmux = terminfo_is_term_family(term, "tmux") || os_env_exists("TMUX", true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // truecolor support must be checked before patching/augmenting terminfo
 | 
					  // truecolor support must be checked before patching/augmenting terminfo
 | 
				
			||||||
  tui->rgb = term_has_truecolor(tui, colorterm);
 | 
					  tui->rgb = term_has_truecolor(tui, colorterm);
 | 
				
			||||||
@@ -503,6 +505,13 @@ static void terminfo_start(TUIData *tui)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  flush_buf(tui);
 | 
					  flush_buf(tui);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  xfree(term);
 | 
				
			||||||
 | 
					  xfree(colorterm);
 | 
				
			||||||
 | 
					  xfree(termprg);
 | 
				
			||||||
 | 
					  xfree(vte_version_env);
 | 
				
			||||||
 | 
					  xfree(konsolev_env);
 | 
				
			||||||
 | 
					  xfree(term_program_version_env);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Disable the alternate screen and prepare for the TUI to close.
 | 
					/// Disable the alternate screen and prepare for the TUI to close.
 | 
				
			||||||
@@ -1772,6 +1781,8 @@ void tui_guess_size(TUIData *tui)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  int width = 0;
 | 
					  int width = 0;
 | 
				
			||||||
  int height = 0;
 | 
					  int height = 0;
 | 
				
			||||||
 | 
					  char *lines = NULL;
 | 
				
			||||||
 | 
					  char *columns = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // 1 - try from a system call (ioctl/TIOCGWINSZ on unix)
 | 
					  // 1 - try from a system call (ioctl/TIOCGWINSZ on unix)
 | 
				
			||||||
  if (tui->out_isatty
 | 
					  if (tui->out_isatty
 | 
				
			||||||
@@ -1782,9 +1793,9 @@ void tui_guess_size(TUIData *tui)
 | 
				
			|||||||
  // 2 - use $LINES/$COLUMNS if available
 | 
					  // 2 - use $LINES/$COLUMNS if available
 | 
				
			||||||
  const char *val;
 | 
					  const char *val;
 | 
				
			||||||
  int advance;
 | 
					  int advance;
 | 
				
			||||||
  if ((val = os_getenv("LINES"))
 | 
					  if ((val = os_getenv_noalloc("LINES"))
 | 
				
			||||||
      && sscanf(val, "%d%n", &height, &advance) != EOF && advance
 | 
					      && sscanf(val, "%d%n", &height, &advance) != EOF && advance
 | 
				
			||||||
      && (val = os_getenv("COLUMNS"))
 | 
					      && (val = os_getenv_noalloc("COLUMNS"))
 | 
				
			||||||
      && sscanf(val, "%d%n", &width, &advance) != EOF && advance) {
 | 
					      && sscanf(val, "%d%n", &width, &advance) != EOF && advance) {
 | 
				
			||||||
    goto end;
 | 
					    goto end;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1804,6 +1815,9 @@ void tui_guess_size(TUIData *tui)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Redraw on SIGWINCH event if size didn't change. #23411
 | 
					  // Redraw on SIGWINCH event if size didn't change. #23411
 | 
				
			||||||
  ui_client_set_size(width, height);
 | 
					  ui_client_set_size(width, height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  xfree(lines);
 | 
				
			||||||
 | 
					  xfree(columns);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void unibi_goto(TUIData *tui, int row, int col)
 | 
					static void unibi_goto(TUIData *tui, int row, int col)
 | 
				
			||||||
@@ -1965,7 +1979,7 @@ static void patch_terminfo_bugs(TUIData *tui, const char *term, const char *colo
 | 
				
			|||||||
                                int vte_version, int konsolev, bool iterm_env, bool nsterm)
 | 
					                                int vte_version, int konsolev, bool iterm_env, bool nsterm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  unibi_term *ut = tui->ut;
 | 
					  unibi_term *ut = tui->ut;
 | 
				
			||||||
  const char *xterm_version = os_getenv("XTERM_VERSION");
 | 
					  char *xterm_version = os_getenv("XTERM_VERSION");
 | 
				
			||||||
  bool xterm = terminfo_is_term_family(term, "xterm")
 | 
					  bool xterm = terminfo_is_term_family(term, "xterm")
 | 
				
			||||||
               // Treat Terminal.app as generic xterm-like, for now.
 | 
					               // Treat Terminal.app as generic xterm-like, for now.
 | 
				
			||||||
               || nsterm;
 | 
					               || nsterm;
 | 
				
			||||||
@@ -1977,7 +1991,7 @@ static void patch_terminfo_bugs(TUIData *tui, const char *term, const char *colo
 | 
				
			|||||||
  bool teraterm = terminfo_is_term_family(term, "teraterm");
 | 
					  bool teraterm = terminfo_is_term_family(term, "teraterm");
 | 
				
			||||||
  bool putty = terminfo_is_term_family(term, "putty");
 | 
					  bool putty = terminfo_is_term_family(term, "putty");
 | 
				
			||||||
  bool screen = terminfo_is_term_family(term, "screen");
 | 
					  bool screen = terminfo_is_term_family(term, "screen");
 | 
				
			||||||
  bool tmux = terminfo_is_term_family(term, "tmux") || !!os_getenv("TMUX");
 | 
					  bool tmux = terminfo_is_term_family(term, "tmux") || os_env_exists("TMUX", true);
 | 
				
			||||||
  bool st = terminfo_is_term_family(term, "st");
 | 
					  bool st = terminfo_is_term_family(term, "st");
 | 
				
			||||||
  bool gnome = terminfo_is_term_family(term, "gnome")
 | 
					  bool gnome = terminfo_is_term_family(term, "gnome")
 | 
				
			||||||
               || terminfo_is_term_family(term, "vte");
 | 
					               || terminfo_is_term_family(term, "vte");
 | 
				
			||||||
@@ -2276,6 +2290,8 @@ static void patch_terminfo_bugs(TUIData *tui, const char *term, const char *colo
 | 
				
			|||||||
                        "\x1b]50;\x07");
 | 
					                        "\x1b]50;\x07");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  xfree(xterm_version);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// This adds stuff that is not in standard terminfo as extended unibilium
 | 
					/// This adds stuff that is not in standard terminfo as extended unibilium
 | 
				
			||||||
@@ -2284,6 +2300,7 @@ static void augment_terminfo(TUIData *tui, const char *term, int vte_version, in
 | 
				
			|||||||
                             const char *weztermv, bool iterm_env, bool nsterm)
 | 
					                             const char *weztermv, bool iterm_env, bool nsterm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  unibi_term *ut = tui->ut;
 | 
					  unibi_term *ut = tui->ut;
 | 
				
			||||||
 | 
					  char *xterm_version = os_getenv("XTERM_VERSION");
 | 
				
			||||||
  bool xterm = terminfo_is_term_family(term, "xterm")
 | 
					  bool xterm = terminfo_is_term_family(term, "xterm")
 | 
				
			||||||
               // Treat Terminal.app as generic xterm-like, for now.
 | 
					               // Treat Terminal.app as generic xterm-like, for now.
 | 
				
			||||||
               || nsterm;
 | 
					               || nsterm;
 | 
				
			||||||
@@ -2294,7 +2311,7 @@ static void augment_terminfo(TUIData *tui, const char *term, int vte_version, in
 | 
				
			|||||||
  bool teraterm = terminfo_is_term_family(term, "teraterm");
 | 
					  bool teraterm = terminfo_is_term_family(term, "teraterm");
 | 
				
			||||||
  bool putty = terminfo_is_term_family(term, "putty");
 | 
					  bool putty = terminfo_is_term_family(term, "putty");
 | 
				
			||||||
  bool screen = terminfo_is_term_family(term, "screen");
 | 
					  bool screen = terminfo_is_term_family(term, "screen");
 | 
				
			||||||
  bool tmux = terminfo_is_term_family(term, "tmux") || !!os_getenv("TMUX");
 | 
					  bool tmux = terminfo_is_term_family(term, "tmux") || os_env_exists("TMUX", true);
 | 
				
			||||||
  bool st = terminfo_is_term_family(term, "st");
 | 
					  bool st = terminfo_is_term_family(term, "st");
 | 
				
			||||||
  bool iterm = terminfo_is_term_family(term, "iterm")
 | 
					  bool iterm = terminfo_is_term_family(term, "iterm")
 | 
				
			||||||
               || terminfo_is_term_family(term, "iterm2")
 | 
					               || terminfo_is_term_family(term, "iterm2")
 | 
				
			||||||
@@ -2305,7 +2322,6 @@ static void augment_terminfo(TUIData *tui, const char *term, int vte_version, in
 | 
				
			|||||||
  // None of the following work over SSH; see :help TERM .
 | 
					  // None of the following work over SSH; see :help TERM .
 | 
				
			||||||
  bool iterm_pretending_xterm = xterm && iterm_env;
 | 
					  bool iterm_pretending_xterm = xterm && iterm_env;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char *xterm_version = os_getenv("XTERM_VERSION");
 | 
					 | 
				
			||||||
  bool true_xterm = xterm && !!xterm_version && !bsdvt;
 | 
					  bool true_xterm = xterm && !!xterm_version && !bsdvt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Only define this capability for terminal types that we know understand it.
 | 
					  // Only define this capability for terminal types that we know understand it.
 | 
				
			||||||
@@ -2468,6 +2484,8 @@ static void augment_terminfo(TUIData *tui, const char *term, int vte_version, in
 | 
				
			|||||||
    // Kitty keyboard protocol
 | 
					    // Kitty keyboard protocol
 | 
				
			||||||
    tui->input.key_encoding = kKeyEncodingXterm;
 | 
					    tui->input.key_encoding = kKeyEncodingXterm;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  xfree(xterm_version);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool should_invisible(TUIData *tui)
 | 
					static bool should_invisible(TUIData *tui)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,7 +63,7 @@ uint64_t ui_client_start_server(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#ifdef MSWIN
 | 
					#ifdef MSWIN
 | 
				
			||||||
  // TODO(justinmk): detach breaks `tt.setup_child_nvim` tests on Windows?
 | 
					  // TODO(justinmk): detach breaks `tt.setup_child_nvim` tests on Windows?
 | 
				
			||||||
  bool detach = os_env_exists("__NVIM_DETACH");
 | 
					  bool detach = os_env_exists("__NVIM_DETACH", true);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  bool detach = true;
 | 
					  bool detach = true;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -172,7 +172,7 @@ void ui_client_run(bool remote_ui)
 | 
				
			|||||||
  ui_client_attach(width, height, term, rgb);
 | 
					  ui_client_attach(width, height, term, rgb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO(justinmk): this is for log_spec. Can remove this after nvim_log #7062 is merged.
 | 
					  // TODO(justinmk): this is for log_spec. Can remove this after nvim_log #7062 is merged.
 | 
				
			||||||
  if (os_env_exists("__NVIM_TEST_LOG")) {
 | 
					  if (os_env_exists("__NVIM_TEST_LOG", true)) {
 | 
				
			||||||
    ELOG("test log message");
 | 
					    ELOG("test log message");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								test/functional/core/env_spec.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								test/functional/core/env_spec.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					local t = require('test.testutil')
 | 
				
			||||||
 | 
					local n = require('test.functional.testnvim')()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local eq = t.eq
 | 
				
			||||||
 | 
					local clear = n.clear
 | 
				
			||||||
 | 
					local exec_capture = n.exec_capture
 | 
				
			||||||
 | 
					local command = n.command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('vim.uv', function()
 | 
				
			||||||
 | 
					  before_each(function()
 | 
				
			||||||
 | 
					    clear()
 | 
				
			||||||
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -- Subsequential env var assignment consistency
 | 
				
			||||||
 | 
					  -- see: issue 32550
 | 
				
			||||||
 | 
					  it('vim.uv.os_setenv(), vim.uv.os_unsetenv() consistency', function()
 | 
				
			||||||
 | 
					    eq('', exec_capture('echo $FOO'))
 | 
				
			||||||
 | 
					    command('lua vim.uv.os_setenv("FOO", "bar")')
 | 
				
			||||||
 | 
					    eq('bar', exec_capture('echo $FOO'))
 | 
				
			||||||
 | 
					    command('lua vim.uv.os_setenv("FOO", "fizz")')
 | 
				
			||||||
 | 
					    eq('fizz', exec_capture('echo $FOO'))
 | 
				
			||||||
 | 
					    command('lua vim.uv.os_unsetenv("FOO")')
 | 
				
			||||||
 | 
					    eq('', exec_capture('echo $FOO'))
 | 
				
			||||||
 | 
					    command('lua vim.uv.os_setenv("FOO", "buzz")')
 | 
				
			||||||
 | 
					    eq('buzz', exec_capture('echo $FOO'))
 | 
				
			||||||
 | 
					  end)
 | 
				
			||||||
 | 
					end)
 | 
				
			||||||
@@ -13,8 +13,8 @@ local OK = 0
 | 
				
			|||||||
local cimp = cimport('./src/nvim/os/os.h')
 | 
					local cimp = cimport('./src/nvim/os/os.h')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('env.c', function()
 | 
					describe('env.c', function()
 | 
				
			||||||
  local function os_env_exists(name)
 | 
					  local function os_env_exists(name, nonempty)
 | 
				
			||||||
    return cimp.os_env_exists(to_cstr(name))
 | 
					    return cimp.os_env_exists(to_cstr(name), nonempty)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local function os_setenv(name, value, override)
 | 
					  local function os_setenv(name, value, override)
 | 
				
			||||||
@@ -34,17 +34,45 @@ describe('env.c', function()
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  itp('os_env_exists', function()
 | 
					  local function os_getenv_noalloc(name)
 | 
				
			||||||
    eq(false, os_env_exists(''))
 | 
					    local rval = cimp.os_getenv_noalloc(to_cstr(name))
 | 
				
			||||||
    eq(false, os_env_exists('      '))
 | 
					    if rval ~= NULL then
 | 
				
			||||||
    eq(false, os_env_exists('\t'))
 | 
					      return ffi.string(rval)
 | 
				
			||||||
    eq(false, os_env_exists('\n'))
 | 
					    else
 | 
				
			||||||
    eq(false, os_env_exists('AaあB <= very weird name...'))
 | 
					      return NULL
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  itp('os_env_exists(..., false)', function()
 | 
				
			||||||
 | 
					    eq(false, os_env_exists('', false))
 | 
				
			||||||
 | 
					    eq(false, os_env_exists('      ', false))
 | 
				
			||||||
 | 
					    eq(false, os_env_exists('\t', false))
 | 
				
			||||||
 | 
					    eq(false, os_env_exists('\n', false))
 | 
				
			||||||
 | 
					    eq(false, os_env_exists('AaあB <= very weird name...', false))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    local varname = 'NVIM_UNIT_TEST_os_env_exists'
 | 
					    local varname = 'NVIM_UNIT_TEST_os_env_exists'
 | 
				
			||||||
    eq(false, os_env_exists(varname))
 | 
					    eq(false, os_env_exists(varname, false))
 | 
				
			||||||
    eq(OK, os_setenv(varname, 'foo bar baz ...', 1))
 | 
					    eq(OK, os_setenv(varname, 'foo bar baz ...', 1))
 | 
				
			||||||
    eq(true, os_env_exists(varname))
 | 
					    eq(true, os_env_exists(varname, false))
 | 
				
			||||||
 | 
					    eq(OK, os_setenv(varname, 'f', 1))
 | 
				
			||||||
 | 
					    eq(true, os_env_exists(varname, true))
 | 
				
			||||||
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  itp('os_env_exists(..., true)', function()
 | 
				
			||||||
 | 
					    eq(false, os_env_exists('', true))
 | 
				
			||||||
 | 
					    eq(false, os_env_exists('      ', true))
 | 
				
			||||||
 | 
					    eq(false, os_env_exists('\t', true))
 | 
				
			||||||
 | 
					    eq(false, os_env_exists('\n', true))
 | 
				
			||||||
 | 
					    eq(false, os_env_exists('AaあB <= very weird name...', true))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local varname = 'NVIM_UNIT_TEST_os_env_defined'
 | 
				
			||||||
 | 
					    eq(false, os_env_exists(varname, true))
 | 
				
			||||||
 | 
					    eq(OK, os_setenv(varname, '', 1))
 | 
				
			||||||
 | 
					    eq(false, os_env_exists(varname, true))
 | 
				
			||||||
 | 
					    eq(OK, os_setenv(varname, 'foo bar baz ...', 1))
 | 
				
			||||||
 | 
					    eq(true, os_env_exists(varname, true))
 | 
				
			||||||
 | 
					    eq(OK, os_setenv(varname, 'f', 1))
 | 
				
			||||||
 | 
					    eq(true, os_env_exists(varname, true))
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe('os_setenv', function()
 | 
					  describe('os_setenv', function()
 | 
				
			||||||
@@ -130,6 +158,10 @@ describe('env.c', function()
 | 
				
			|||||||
      os_setenv(name, value, 1)
 | 
					      os_setenv(name, value, 1)
 | 
				
			||||||
      eq(value, os_getenv(name))
 | 
					      eq(value, os_getenv(name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      -- Shortest non-empty value
 | 
				
			||||||
 | 
					      os_setenv(name, 'z', 1)
 | 
				
			||||||
 | 
					      eq('z', os_getenv(name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      -- Get a big value.
 | 
					      -- Get a big value.
 | 
				
			||||||
      local bigval = ('x'):rep(256)
 | 
					      local bigval = ('x'):rep(256)
 | 
				
			||||||
      eq(OK, os_setenv(name, bigval, 1))
 | 
					      eq(OK, os_setenv(name, bigval, 1))
 | 
				
			||||||
@@ -147,6 +179,42 @@ describe('env.c', function()
 | 
				
			|||||||
    end)
 | 
					    end)
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe('os_getenv_noalloc', function()
 | 
				
			||||||
 | 
					    itp('reads an env var without memory allocation', function()
 | 
				
			||||||
 | 
					      local name = 'NVIM_UNIT_TEST_GETENV_1N'
 | 
				
			||||||
 | 
					      local value = 'NVIM_UNIT_TEST_GETENV_1V'
 | 
				
			||||||
 | 
					      eq(NULL, os_getenv_noalloc(name))
 | 
				
			||||||
 | 
					      -- Use os_setenv because Lua doesn't have setenv.
 | 
				
			||||||
 | 
					      os_setenv(name, value, 1)
 | 
				
			||||||
 | 
					      eq(value, os_getenv_noalloc(name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      -- Shortest non-empty value
 | 
				
			||||||
 | 
					      os_setenv(name, 'z', 1)
 | 
				
			||||||
 | 
					      eq('z', os_getenv(name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      local bigval = ('x'):rep(256)
 | 
				
			||||||
 | 
					      eq(OK, os_setenv(name, bigval, 1))
 | 
				
			||||||
 | 
					      eq(bigval, os_getenv_noalloc(name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      -- Variable size above NameBuff size gets truncated
 | 
				
			||||||
 | 
					      -- This assumes MAXPATHL is 4096 bytes.
 | 
				
			||||||
 | 
					      local verybigval = ('y'):rep(4096)
 | 
				
			||||||
 | 
					      local trunc = string.sub(verybigval, 0, 4095)
 | 
				
			||||||
 | 
					      eq(OK, os_setenv(name, verybigval, 1))
 | 
				
			||||||
 | 
					      eq(trunc, os_getenv_noalloc(name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      -- Set non-empty, then set empty.
 | 
				
			||||||
 | 
					      eq(OK, os_setenv(name, 'non-empty', 1))
 | 
				
			||||||
 | 
					      eq('non-empty', os_getenv(name))
 | 
				
			||||||
 | 
					      eq(OK, os_setenv(name, '', 1))
 | 
				
			||||||
 | 
					      eq(NULL, os_getenv_noalloc(name))
 | 
				
			||||||
 | 
					    end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    itp('returns NULL if the env var is not found', function()
 | 
				
			||||||
 | 
					      eq(NULL, os_getenv_noalloc('NVIM_UNIT_TEST_GETENV_NOTFOUND'))
 | 
				
			||||||
 | 
					    end)
 | 
				
			||||||
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  itp('os_unsetenv', function()
 | 
					  itp('os_unsetenv', function()
 | 
				
			||||||
    local name = 'TEST_UNSETENV'
 | 
					    local name = 'TEST_UNSETENV'
 | 
				
			||||||
    local value = 'TESTVALUE'
 | 
					    local value = 'TESTVALUE'
 | 
				
			||||||
@@ -156,7 +224,7 @@ describe('env.c', function()
 | 
				
			|||||||
    -- Depending on the platform the var might be unset or set as ''
 | 
					    -- Depending on the platform the var might be unset or set as ''
 | 
				
			||||||
    assert.True(os_getenv(name) == nil or os_getenv(name) == '')
 | 
					    assert.True(os_getenv(name) == nil or os_getenv(name) == '')
 | 
				
			||||||
    if os_getenv(name) == nil then
 | 
					    if os_getenv(name) == nil then
 | 
				
			||||||
      eq(false, os_env_exists(name))
 | 
					      eq(false, os_env_exists(name, false))
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end)
 | 
					  end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user