Use uv_os_homedir and current directory as backup when $HOME is not set (#13657)

Close https://github.com/neovim/neovim/issues/8614

Use uv_os_homedir and current directory as backup if HOME env is not set.
Allocate homedir only if var is not NULL.
This commit is contained in:
ffanzhang
2021-01-10 16:46:25 -08:00
committed by GitHub
parent 635930dcd7
commit 0860d9c164
2 changed files with 107 additions and 7 deletions

View File

@@ -394,13 +394,21 @@ void os_get_hostname(char *hostname, size_t size)
}
/// To get the "real" home directory:
/// - get value of $HOME
/// 1. get value of $HOME
/// 2. if $HOME is not set, try the following
/// For Windows:
/// 1. assemble homedir using HOMEDRIVE and HOMEPATH
/// 2. try os_homedir()
/// 3. resolve a direct reference to another system variable
/// 4. guess C drive
/// For Unix:
/// - go to that directory
/// - do os_dirname() to get the real name of that directory.
/// This also works with mounts and links.
/// Don't do this for Windows, it will change the "current dir" for a drive.
/// 1. try os_homedir()
/// 2. go to that directory
/// This also works with mounts and links.
/// Don't do this for Windows, it will change the "current dir" for a drive.
/// 3. fall back to current working directory as a last resort
static char *homedir = NULL;
static char *os_homedir(void);
void init_homedir(void)
{
@@ -430,7 +438,7 @@ void init_homedir(void)
}
}
if (var == NULL) {
var = os_getenv("USERPROFILE");
var = os_homedir();
}
// Weird but true: $HOME may contain an indirect reference to another
@@ -440,6 +448,7 @@ void init_homedir(void)
const char *p = strchr(var + 1, '%');
if (p != NULL) {
vim_snprintf(os_buf, (size_t)(p - var), "%s", var + 1);
var = NULL;
const char *exp = os_getenv(os_buf);
if (exp != NULL && *exp != NUL
&& STRLEN(exp) + STRLEN(p) < MAXPATHL) {
@@ -458,8 +467,12 @@ void init_homedir(void)
}
#endif
if (var != NULL) {
#ifdef UNIX
if (var == NULL) {
var = os_homedir();
}
if (var != NULL) {
// Change to the directory and get the actual path. This resolves
// links. Don't do it when we can't return.
if (os_dirname((char_u *)os_buf, MAXPATHL) == OK && os_chdir(os_buf) == 0) {
@@ -470,11 +483,37 @@ void init_homedir(void)
EMSG(_(e_prev_dir));
}
}
}
// Fall back to current working directory if home is not found
if ((var == NULL || *var == NUL)
&& os_dirname((char_u *)os_buf, sizeof(os_buf)) == OK) {
var = os_buf;
}
#endif
if (var != NULL) {
homedir = xstrdup(var);
}
}
static char homedir_buf[MAXPATHL];
static char *os_homedir(void)
{
homedir_buf[0] = NUL;
size_t homedir_size = MAXPATHL;
uv_mutex_lock(&mutex);
// http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_homedir
int ret_value = uv_os_homedir(homedir_buf, &homedir_size);
uv_mutex_unlock(&mutex);
if (ret_value == 0 && homedir_size < MAXPATHL) {
return homedir_buf;
}
ELOG("uv_os_homedir() failed %d: %s", ret_value, os_strerror(ret_value));
homedir_buf[0] = NUL;
return NULL;
}
#if defined(EXITFREE)
void free_homedir(void)